1 /* 2 * /proc/sys support 3 */ 4 5 #include <linux/sysctl.h> 6 #include <linux/proc_fs.h> 7 #include <linux/security.h> 8 #include "internal.h" 9 10 static struct dentry_operations proc_sys_dentry_operations; 11 static const struct file_operations proc_sys_file_operations; 12 static const struct inode_operations proc_sys_inode_operations; 13 14 static void proc_sys_refresh_inode(struct inode *inode, struct ctl_table *table) 15 { 16 /* Refresh the cached information bits in the inode */ 17 if (table) { 18 inode->i_uid = 0; 19 inode->i_gid = 0; 20 inode->i_mode = table->mode; 21 if (table->proc_handler) { 22 inode->i_mode |= S_IFREG; 23 inode->i_nlink = 1; 24 } else { 25 inode->i_mode |= S_IFDIR; 26 inode->i_nlink = 0; /* It is too hard to figure out */ 27 } 28 } 29 } 30 31 static struct inode *proc_sys_make_inode(struct inode *dir, struct ctl_table *table) 32 { 33 struct inode *inode; 34 struct proc_inode *dir_ei, *ei; 35 int depth; 36 37 inode = new_inode(dir->i_sb); 38 if (!inode) 39 goto out; 40 41 /* A directory is always one deeper than it's parent */ 42 dir_ei = PROC_I(dir); 43 depth = dir_ei->fd + 1; 44 45 ei = PROC_I(inode); 46 ei->fd = depth; 47 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 48 inode->i_op = &proc_sys_inode_operations; 49 inode->i_fop = &proc_sys_file_operations; 50 inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */ 51 proc_sys_refresh_inode(inode, table); 52 out: 53 return inode; 54 } 55 56 static struct dentry *proc_sys_ancestor(struct dentry *dentry, int depth) 57 { 58 for (;;) { 59 struct proc_inode *ei; 60 61 ei = PROC_I(dentry->d_inode); 62 if (ei->fd == depth) 63 break; /* found */ 64 65 dentry = dentry->d_parent; 66 } 67 return dentry; 68 } 69 70 static struct ctl_table *proc_sys_lookup_table_one(struct ctl_table *table, 71 struct qstr *name) 72 { 73 int len; 74 for ( ; table->ctl_name || table->procname; table++) { 75 76 if (!table->procname) 77 continue; 78 79 len = strlen(table->procname); 80 if (len != name->len) 81 continue; 82 83 if (memcmp(table->procname, name->name, len) != 0) 84 continue; 85 86 /* I have a match */ 87 return table; 88 } 89 return NULL; 90 } 91 92 static struct ctl_table *proc_sys_lookup_table(struct dentry *dentry, 93 struct ctl_table *table) 94 { 95 struct dentry *ancestor; 96 struct proc_inode *ei; 97 int depth, i; 98 99 ei = PROC_I(dentry->d_inode); 100 depth = ei->fd; 101 102 if (depth == 0) 103 return table; 104 105 for (i = 1; table && (i <= depth); i++) { 106 ancestor = proc_sys_ancestor(dentry, i); 107 table = proc_sys_lookup_table_one(table, &ancestor->d_name); 108 if (table) 109 table = table->child; 110 } 111 return table; 112 113 } 114 static struct ctl_table *proc_sys_lookup_entry(struct dentry *dparent, 115 struct qstr *name, 116 struct ctl_table *table) 117 { 118 table = proc_sys_lookup_table(dparent, table); 119 if (table) 120 table = proc_sys_lookup_table_one(table, name); 121 return table; 122 } 123 124 static struct ctl_table *do_proc_sys_lookup(struct dentry *parent, 125 struct qstr *name, 126 struct ctl_table_header **ptr) 127 { 128 struct ctl_table_header *head; 129 struct ctl_table *table = NULL; 130 131 for (head = sysctl_head_next(NULL); head; 132 head = sysctl_head_next(head)) { 133 table = proc_sys_lookup_entry(parent, name, head->ctl_table); 134 if (table) 135 break; 136 } 137 *ptr = head; 138 return table; 139 } 140 141 static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, 142 struct nameidata *nd) 143 { 144 struct ctl_table_header *head; 145 struct inode *inode; 146 struct dentry *err; 147 struct ctl_table *table; 148 149 err = ERR_PTR(-ENOENT); 150 table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); 151 if (!table) 152 goto out; 153 154 err = ERR_PTR(-ENOMEM); 155 inode = proc_sys_make_inode(dir, table); 156 if (!inode) 157 goto out; 158 159 err = NULL; 160 dentry->d_op = &proc_sys_dentry_operations; 161 d_add(dentry, inode); 162 163 out: 164 sysctl_head_finish(head); 165 return err; 166 } 167 168 static ssize_t proc_sys_read(struct file *filp, char __user *buf, 169 size_t count, loff_t *ppos) 170 { 171 struct dentry *dentry = filp->f_dentry; 172 struct ctl_table_header *head; 173 struct ctl_table *table; 174 ssize_t error; 175 size_t res; 176 177 table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); 178 /* Has the sysctl entry disappeared on us? */ 179 error = -ENOENT; 180 if (!table) 181 goto out; 182 183 /* Has the sysctl entry been replaced by a directory? */ 184 error = -EISDIR; 185 if (!table->proc_handler) 186 goto out; 187 188 /* 189 * At this point we know that the sysctl was not unregistered 190 * and won't be until we finish. 191 */ 192 error = -EPERM; 193 if (sysctl_perm(table, MAY_READ)) 194 goto out; 195 196 /* careful: calling conventions are nasty here */ 197 res = count; 198 error = table->proc_handler(table, 0, filp, buf, &res, ppos); 199 if (!error) 200 error = res; 201 out: 202 sysctl_head_finish(head); 203 204 return error; 205 } 206 207 static ssize_t proc_sys_write(struct file *filp, const char __user *buf, 208 size_t count, loff_t *ppos) 209 { 210 struct dentry *dentry = filp->f_dentry; 211 struct ctl_table_header *head; 212 struct ctl_table *table; 213 ssize_t error; 214 size_t res; 215 216 table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); 217 /* Has the sysctl entry disappeared on us? */ 218 error = -ENOENT; 219 if (!table) 220 goto out; 221 222 /* Has the sysctl entry been replaced by a directory? */ 223 error = -EISDIR; 224 if (!table->proc_handler) 225 goto out; 226 227 /* 228 * At this point we know that the sysctl was not unregistered 229 * and won't be until we finish. 230 */ 231 error = -EPERM; 232 if (sysctl_perm(table, MAY_WRITE)) 233 goto out; 234 235 /* careful: calling conventions are nasty here */ 236 res = count; 237 error = table->proc_handler(table, 1, filp, (char __user *)buf, 238 &res, ppos); 239 if (!error) 240 error = res; 241 out: 242 sysctl_head_finish(head); 243 244 return error; 245 } 246 247 248 static int proc_sys_fill_cache(struct file *filp, void *dirent, 249 filldir_t filldir, struct ctl_table *table) 250 { 251 struct ctl_table_header *head; 252 struct ctl_table *child_table = NULL; 253 struct dentry *child, *dir = filp->f_path.dentry; 254 struct inode *inode; 255 struct qstr qname; 256 ino_t ino = 0; 257 unsigned type = DT_UNKNOWN; 258 int ret; 259 260 qname.name = table->procname; 261 qname.len = strlen(table->procname); 262 qname.hash = full_name_hash(qname.name, qname.len); 263 264 /* Suppress duplicates. 265 * Only fill a directory entry if it is the value that 266 * an ordinary lookup of that name returns. Hide all 267 * others. 268 * 269 * If we ever cache this translation in the dcache 270 * I should do a dcache lookup first. But for now 271 * it is just simpler not to. 272 */ 273 ret = 0; 274 child_table = do_proc_sys_lookup(dir, &qname, &head); 275 sysctl_head_finish(head); 276 if (child_table != table) 277 return 0; 278 279 child = d_lookup(dir, &qname); 280 if (!child) { 281 struct dentry *new; 282 new = d_alloc(dir, &qname); 283 if (new) { 284 inode = proc_sys_make_inode(dir->d_inode, table); 285 if (!inode) 286 child = ERR_PTR(-ENOMEM); 287 else { 288 new->d_op = &proc_sys_dentry_operations; 289 d_add(new, inode); 290 } 291 if (child) 292 dput(new); 293 else 294 child = new; 295 } 296 } 297 if (!child || IS_ERR(child) || !child->d_inode) 298 goto end_instantiate; 299 inode = child->d_inode; 300 if (inode) { 301 ino = inode->i_ino; 302 type = inode->i_mode >> 12; 303 } 304 dput(child); 305 end_instantiate: 306 if (!ino) 307 ino= find_inode_number(dir, &qname); 308 if (!ino) 309 ino = 1; 310 return filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type); 311 } 312 313 static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir) 314 { 315 struct dentry *dentry = filp->f_dentry; 316 struct inode *inode = dentry->d_inode; 317 struct ctl_table_header *head = NULL; 318 struct ctl_table *table; 319 unsigned long pos; 320 int ret; 321 322 ret = -ENOTDIR; 323 if (!S_ISDIR(inode->i_mode)) 324 goto out; 325 326 ret = 0; 327 /* Avoid a switch here: arm builds fail with missing __cmpdi2 */ 328 if (filp->f_pos == 0) { 329 if (filldir(dirent, ".", 1, filp->f_pos, 330 inode->i_ino, DT_DIR) < 0) 331 goto out; 332 filp->f_pos++; 333 } 334 if (filp->f_pos == 1) { 335 if (filldir(dirent, "..", 2, filp->f_pos, 336 parent_ino(dentry), DT_DIR) < 0) 337 goto out; 338 filp->f_pos++; 339 } 340 pos = 2; 341 342 /* - Find each instance of the directory 343 * - Read all entries in each instance 344 * - Before returning an entry to user space lookup the entry 345 * by name and if I find a different entry don't return 346 * this one because it means it is a buried dup. 347 * For sysctl this should only happen for directory entries. 348 */ 349 for (head = sysctl_head_next(NULL); head; head = sysctl_head_next(head)) { 350 table = proc_sys_lookup_table(dentry, head->ctl_table); 351 352 if (!table) 353 continue; 354 355 for (; table->ctl_name || table->procname; table++, pos++) { 356 /* Can't do anything without a proc name */ 357 if (!table->procname) 358 continue; 359 360 if (pos < filp->f_pos) 361 continue; 362 363 if (proc_sys_fill_cache(filp, dirent, filldir, table) < 0) 364 goto out; 365 filp->f_pos = pos + 1; 366 } 367 } 368 ret = 1; 369 out: 370 sysctl_head_finish(head); 371 return ret; 372 } 373 374 static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *nd) 375 { 376 /* 377 * sysctl entries that are not writeable, 378 * are _NOT_ writeable, capabilities or not. 379 */ 380 struct ctl_table_header *head; 381 struct ctl_table *table; 382 struct dentry *dentry; 383 int mode; 384 int depth; 385 int error; 386 387 head = NULL; 388 depth = PROC_I(inode)->fd; 389 390 /* First check the cached permissions, in case we don't have 391 * enough information to lookup the sysctl table entry. 392 */ 393 error = -EACCES; 394 mode = inode->i_mode; 395 396 if (current->euid == 0) 397 mode >>= 6; 398 else if (in_group_p(0)) 399 mode >>= 3; 400 401 if ((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask) 402 error = 0; 403 404 /* If we can't get a sysctl table entry the permission 405 * checks on the cached mode will have to be enough. 406 */ 407 if (!nd || !depth) 408 goto out; 409 410 dentry = nd->path.dentry; 411 table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); 412 413 /* If the entry does not exist deny permission */ 414 error = -EACCES; 415 if (!table) 416 goto out; 417 418 /* Use the permissions on the sysctl table entry */ 419 error = sysctl_perm(table, mask); 420 out: 421 sysctl_head_finish(head); 422 return error; 423 } 424 425 static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr) 426 { 427 struct inode *inode = dentry->d_inode; 428 int error; 429 430 if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) 431 return -EPERM; 432 433 error = inode_change_ok(inode, attr); 434 if (!error) 435 error = inode_setattr(inode, attr); 436 437 return error; 438 } 439 440 /* I'm lazy and don't distinguish between files and directories, 441 * until access time. 442 */ 443 static const struct file_operations proc_sys_file_operations = { 444 .read = proc_sys_read, 445 .write = proc_sys_write, 446 .readdir = proc_sys_readdir, 447 }; 448 449 static const struct inode_operations proc_sys_inode_operations = { 450 .lookup = proc_sys_lookup, 451 .permission = proc_sys_permission, 452 .setattr = proc_sys_setattr, 453 }; 454 455 static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd) 456 { 457 struct ctl_table_header *head; 458 struct ctl_table *table; 459 table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); 460 proc_sys_refresh_inode(dentry->d_inode, table); 461 sysctl_head_finish(head); 462 return !!table; 463 } 464 465 static struct dentry_operations proc_sys_dentry_operations = { 466 .d_revalidate = proc_sys_revalidate, 467 }; 468 469 static struct proc_dir_entry *proc_sys_root; 470 471 int proc_sys_init(void) 472 { 473 proc_sys_root = proc_mkdir("sys", NULL); 474 proc_sys_root->proc_iops = &proc_sys_inode_operations; 475 proc_sys_root->proc_fops = &proc_sys_file_operations; 476 proc_sys_root->nlink = 0; 477 return 0; 478 } 479