| 2155 | */ |
| 2156 | |
| 2157 | static int |
| 2158 | sysctl_root(SYSCTL_HANDLER_ARGS) |
| 2159 | { |
| 2160 | struct sysctl_oid *oid; |
| 2161 | struct rm_priotracker tracker; |
| 2162 | int error, indx, lvl; |
| 2163 | |
| 2164 | SYSCTL_RLOCK(&tracker); |
| 2165 | |
| 2166 | error = sysctl_find_oid(arg1, arg2, &oid, &indx, req); |
| 2167 | if (error) |
| 2168 | goto out; |
| 2169 | |
| 2170 | if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { |
| 2171 | /* |
| 2172 | * You can't call a sysctl when it's a node, but has |
| 2173 | * no handler. Inform the user that it's a node. |
| 2174 | * The indx may or may not be the same as namelen. |
| 2175 | */ |
| 2176 | if (oid->oid_handler == NULL) { |
| 2177 | error = EISDIR; |
| 2178 | goto out; |
| 2179 | } |
| 2180 | } |
| 2181 | |
| 2182 | /* Is this sysctl writable? */ |
| 2183 | if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) { |
| 2184 | error = EPERM; |
| 2185 | goto out; |
| 2186 | } |
| 2187 | |
| 2188 | KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL")); |
| 2189 | |
| 2190 | #ifdef CAPABILITY_MODE |
| 2191 | /* |
| 2192 | * If the process is in capability mode, then don't permit reading or |
| 2193 | * writing unless specifically granted for the node. |
| 2194 | */ |
| 2195 | if (IN_CAPABILITY_MODE(req->td)) { |
| 2196 | if ((req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD)) || |
| 2197 | (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))) { |
| 2198 | error = EPERM; |
| 2199 | goto out; |
| 2200 | } |
| 2201 | } |
| 2202 | #endif |
| 2203 | |
| 2204 | /* Is this sysctl sensitive to securelevels? */ |
| 2205 | if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) { |
| 2206 | lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE; |
| 2207 | error = securelevel_gt(req->td->td_ucred, lvl); |
| 2208 | if (error) |
| 2209 | goto out; |
| 2210 | } |
| 2211 | |
| 2212 | /* Is this sysctl writable by only privileged users? */ |
| 2213 | if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) { |
| 2214 | int priv; |
no test coverage detected