diff options
| author | Kentaro Takeda <takedakn@nttdata.co.jp> | 2008-12-16 23:24:15 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-12-31 18:07:37 -0500 |
| commit | be6d3e56a6b9b3a4ee44a0685e39e595073c6f0d (patch) | |
| tree | 3a770f4cc676efeba443b28caa1ad195eeff49bc | |
| parent | 6a94cb73064c952255336cc57731904174b2c58f (diff) | |
introduce new LSM hooks where vfsmount is available.
Add new LSM hooks for path-based checks. Call them on directory-modifying
operations at the points where we still know the vfsmount involved.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/namei.c | 36 | ||||
| -rw-r--r-- | fs/open.c | 5 | ||||
| -rw-r--r-- | include/linux/security.h | 137 | ||||
| -rw-r--r-- | net/unix/af_unix.c | 4 | ||||
| -rw-r--r-- | security/Kconfig | 9 | ||||
| -rw-r--r-- | security/capability.c | 57 | ||||
| -rw-r--r-- | security/security.c | 66 |
7 files changed, 314 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c index af3783fff1de..ab441af4196b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -1556,6 +1556,9 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
| 1556 | * Refuse to truncate files with mandatory locks held on them. | 1556 | * Refuse to truncate files with mandatory locks held on them. |
| 1557 | */ | 1557 | */ |
| 1558 | error = locks_verify_locked(inode); | 1558 | error = locks_verify_locked(inode); |
| 1559 | if (!error) | ||
| 1560 | error = security_path_truncate(&nd->path, 0, | ||
| 1561 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
| 1559 | if (!error) { | 1562 | if (!error) { |
| 1560 | DQUOT_INIT(inode); | 1563 | DQUOT_INIT(inode); |
| 1561 | 1564 | ||
| @@ -1586,7 +1589,11 @@ static int __open_namei_create(struct nameidata *nd, struct path *path, | |||
| 1586 | 1589 | ||
| 1587 | if (!IS_POSIXACL(dir->d_inode)) | 1590 | if (!IS_POSIXACL(dir->d_inode)) |
| 1588 | mode &= ~current->fs->umask; | 1591 | mode &= ~current->fs->umask; |
| 1592 | error = security_path_mknod(&nd->path, path->dentry, mode, 0); | ||
| 1593 | if (error) | ||
| 1594 | goto out_unlock; | ||
| 1589 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); | 1595 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); |
| 1596 | out_unlock: | ||
| 1590 | mutex_unlock(&dir->d_inode->i_mutex); | 1597 | mutex_unlock(&dir->d_inode->i_mutex); |
| 1591 | dput(nd->path.dentry); | 1598 | dput(nd->path.dentry); |
| 1592 | nd->path.dentry = path->dentry; | 1599 | nd->path.dentry = path->dentry; |
| @@ -1999,6 +2006,9 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
| 1999 | error = mnt_want_write(nd.path.mnt); | 2006 | error = mnt_want_write(nd.path.mnt); |
| 2000 | if (error) | 2007 | if (error) |
| 2001 | goto out_dput; | 2008 | goto out_dput; |
| 2009 | error = security_path_mknod(&nd.path, dentry, mode, dev); | ||
| 2010 | if (error) | ||
| 2011 | goto out_drop_write; | ||
| 2002 | switch (mode & S_IFMT) { | 2012 | switch (mode & S_IFMT) { |
| 2003 | case 0: case S_IFREG: | 2013 | case 0: case S_IFREG: |
| 2004 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); | 2014 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); |
| @@ -2011,6 +2021,7 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
| 2011 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); | 2021 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); |
| 2012 | break; | 2022 | break; |
| 2013 | } | 2023 | } |
| 2024 | out_drop_write: | ||
| 2014 | mnt_drop_write(nd.path.mnt); | 2025 | mnt_drop_write(nd.path.mnt); |
| 2015 | out_dput: | 2026 | out_dput: |
| 2016 | dput(dentry); | 2027 | dput(dentry); |
| @@ -2070,7 +2081,11 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
| 2070 | error = mnt_want_write(nd.path.mnt); | 2081 | error = mnt_want_write(nd.path.mnt); |
| 2071 | if (error) | 2082 | if (error) |
| 2072 | goto out_dput; | 2083 | goto out_dput; |
| 2084 | error = security_path_mkdir(&nd.path, dentry, mode); | ||
| 2085 | if (error) | ||
| 2086 | goto out_drop_write; | ||
| 2073 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); | 2087 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
| 2088 | out_drop_write: | ||
| 2074 | mnt_drop_write(nd.path.mnt); | 2089 | mnt_drop_write(nd.path.mnt); |
| 2075 | out_dput: | 2090 | out_dput: |
| 2076 | dput(dentry); | 2091 | dput(dentry); |
| @@ -2180,7 +2195,11 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
| 2180 | error = mnt_want_write(nd.path.mnt); | 2195 | error = mnt_want_write(nd.path.mnt); |
| 2181 | if (error) | 2196 | if (error) |
| 2182 | goto exit3; | 2197 | goto exit3; |
| 2198 | error = security_path_rmdir(&nd.path, dentry); | ||
| 2199 | if (error) | ||
| 2200 | goto exit4; | ||
| 2183 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); | 2201 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
| 2202 | exit4: | ||
| 2184 | mnt_drop_write(nd.path.mnt); | 2203 | mnt_drop_write(nd.path.mnt); |
| 2185 | exit3: | 2204 | exit3: |
| 2186 | dput(dentry); | 2205 | dput(dentry); |
| @@ -2265,7 +2284,11 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
| 2265 | error = mnt_want_write(nd.path.mnt); | 2284 | error = mnt_want_write(nd.path.mnt); |
| 2266 | if (error) | 2285 | if (error) |
| 2267 | goto exit2; | 2286 | goto exit2; |
| 2287 | error = security_path_unlink(&nd.path, dentry); | ||
| 2288 | if (error) | ||
| 2289 | goto exit3; | ||
| 2268 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 2290 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
| 2291 | exit3: | ||
| 2269 | mnt_drop_write(nd.path.mnt); | 2292 | mnt_drop_write(nd.path.mnt); |
| 2270 | exit2: | 2293 | exit2: |
| 2271 | dput(dentry); | 2294 | dput(dentry); |
| @@ -2346,7 +2369,11 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
| 2346 | error = mnt_want_write(nd.path.mnt); | 2369 | error = mnt_want_write(nd.path.mnt); |
| 2347 | if (error) | 2370 | if (error) |
| 2348 | goto out_dput; | 2371 | goto out_dput; |
| 2372 | error = security_path_symlink(&nd.path, dentry, from); | ||
| 2373 | if (error) | ||
| 2374 | goto out_drop_write; | ||
| 2349 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); | 2375 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); |
| 2376 | out_drop_write: | ||
| 2350 | mnt_drop_write(nd.path.mnt); | 2377 | mnt_drop_write(nd.path.mnt); |
| 2351 | out_dput: | 2378 | out_dput: |
| 2352 | dput(dentry); | 2379 | dput(dentry); |
| @@ -2443,7 +2470,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
| 2443 | error = mnt_want_write(nd.path.mnt); | 2470 | error = mnt_want_write(nd.path.mnt); |
| 2444 | if (error) | 2471 | if (error) |
| 2445 | goto out_dput; | 2472 | goto out_dput; |
| 2473 | error = security_path_link(old_path.dentry, &nd.path, new_dentry); | ||
| 2474 | if (error) | ||
| 2475 | goto out_drop_write; | ||
| 2446 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); | 2476 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); |
| 2477 | out_drop_write: | ||
| 2447 | mnt_drop_write(nd.path.mnt); | 2478 | mnt_drop_write(nd.path.mnt); |
| 2448 | out_dput: | 2479 | out_dput: |
| 2449 | dput(new_dentry); | 2480 | dput(new_dentry); |
| @@ -2679,8 +2710,13 @@ asmlinkage long sys_renameat(int olddfd, const char __user *oldname, | |||
| 2679 | error = mnt_want_write(oldnd.path.mnt); | 2710 | error = mnt_want_write(oldnd.path.mnt); |
| 2680 | if (error) | 2711 | if (error) |
| 2681 | goto exit5; | 2712 | goto exit5; |
| 2713 | error = security_path_rename(&oldnd.path, old_dentry, | ||
| 2714 | &newnd.path, new_dentry); | ||
| 2715 | if (error) | ||
| 2716 | goto exit6; | ||
| 2682 | error = vfs_rename(old_dir->d_inode, old_dentry, | 2717 | error = vfs_rename(old_dir->d_inode, old_dentry, |
| 2683 | new_dir->d_inode, new_dentry); | 2718 | new_dir->d_inode, new_dentry); |
| 2719 | exit6: | ||
| 2684 | mnt_drop_write(oldnd.path.mnt); | 2720 | mnt_drop_write(oldnd.path.mnt); |
| 2685 | exit5: | 2721 | exit5: |
| 2686 | dput(new_dentry); | 2722 | dput(new_dentry); |
| @@ -272,6 +272,8 @@ static long do_sys_truncate(const char __user *pathname, loff_t length) | |||
| 272 | goto put_write_and_out; | 272 | goto put_write_and_out; |
| 273 | 273 | ||
| 274 | error = locks_verify_truncate(inode, NULL, length); | 274 | error = locks_verify_truncate(inode, NULL, length); |
| 275 | if (!error) | ||
| 276 | error = security_path_truncate(&path, length, 0); | ||
| 275 | if (!error) { | 277 | if (!error) { |
| 276 | DQUOT_INIT(inode); | 278 | DQUOT_INIT(inode); |
| 277 | error = do_truncate(path.dentry, length, 0, NULL); | 279 | error = do_truncate(path.dentry, length, 0, NULL); |
| @@ -329,6 +331,9 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) | |||
| 329 | 331 | ||
| 330 | error = locks_verify_truncate(inode, file, length); | 332 | error = locks_verify_truncate(inode, file, length); |
| 331 | if (!error) | 333 | if (!error) |
| 334 | error = security_path_truncate(&file->f_path, length, | ||
| 335 | ATTR_MTIME|ATTR_CTIME); | ||
| 336 | if (!error) | ||
| 332 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); | 337 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); |
| 333 | out_putf: | 338 | out_putf: |
| 334 | fput(file); | 339 | fput(file); |
diff --git a/include/linux/security.h b/include/linux/security.h index 3416cb85e77b..b92b5e453f64 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -335,17 +335,37 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 335 | * @dir contains the inode structure of the parent directory of the new link. | 335 | * @dir contains the inode structure of the parent directory of the new link. |
| 336 | * @new_dentry contains the dentry structure for the new link. | 336 | * @new_dentry contains the dentry structure for the new link. |
| 337 | * Return 0 if permission is granted. | 337 | * Return 0 if permission is granted. |
| 338 | * @path_link: | ||
| 339 | * Check permission before creating a new hard link to a file. | ||
| 340 | * @old_dentry contains the dentry structure for an existing link | ||
| 341 | * to the file. | ||
| 342 | * @new_dir contains the path structure of the parent directory of | ||
| 343 | * the new link. | ||
| 344 | * @new_dentry contains the dentry structure for the new link. | ||
| 345 | * Return 0 if permission is granted. | ||
| 338 | * @inode_unlink: | 346 | * @inode_unlink: |
| 339 | * Check the permission to remove a hard link to a file. | 347 | * Check the permission to remove a hard link to a file. |
| 340 | * @dir contains the inode structure of parent directory of the file. | 348 | * @dir contains the inode structure of parent directory of the file. |
| 341 | * @dentry contains the dentry structure for file to be unlinked. | 349 | * @dentry contains the dentry structure for file to be unlinked. |
| 342 | * Return 0 if permission is granted. | 350 | * Return 0 if permission is granted. |
| 351 | * @path_unlink: | ||
| 352 | * Check the permission to remove a hard link to a file. | ||
| 353 | * @dir contains the path structure of parent directory of the file. | ||
| 354 | * @dentry contains the dentry structure for file to be unlinked. | ||
| 355 | * Return 0 if permission is granted. | ||
| 343 | * @inode_symlink: | 356 | * @inode_symlink: |
| 344 | * Check the permission to create a symbolic link to a file. | 357 | * Check the permission to create a symbolic link to a file. |
| 345 | * @dir contains the inode structure of parent directory of the symbolic link. | 358 | * @dir contains the inode structure of parent directory of the symbolic link. |
| 346 | * @dentry contains the dentry structure of the symbolic link. | 359 | * @dentry contains the dentry structure of the symbolic link. |
| 347 | * @old_name contains the pathname of file. | 360 | * @old_name contains the pathname of file. |
| 348 | * Return 0 if permission is granted. | 361 | * Return 0 if permission is granted. |
| 362 | * @path_symlink: | ||
| 363 | * Check the permission to create a symbolic link to a file. | ||
| 364 | * @dir contains the path structure of parent directory of | ||
| 365 | * the symbolic link. | ||
| 366 | * @dentry contains the dentry structure of the symbolic link. | ||
| 367 | * @old_name contains the pathname of file. | ||
| 368 | * Return 0 if permission is granted. | ||
| 349 | * @inode_mkdir: | 369 | * @inode_mkdir: |
| 350 | * Check permissions to create a new directory in the existing directory | 370 | * Check permissions to create a new directory in the existing directory |
| 351 | * associated with inode strcture @dir. | 371 | * associated with inode strcture @dir. |
| @@ -353,11 +373,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 353 | * @dentry contains the dentry structure of new directory. | 373 | * @dentry contains the dentry structure of new directory. |
| 354 | * @mode contains the mode of new directory. | 374 | * @mode contains the mode of new directory. |
| 355 | * Return 0 if permission is granted. | 375 | * Return 0 if permission is granted. |
| 376 | * @path_mkdir: | ||
| 377 | * Check permissions to create a new directory in the existing directory | ||
| 378 | * associated with path strcture @path. | ||
| 379 | * @dir containst the path structure of parent of the directory | ||
| 380 | * to be created. | ||
| 381 | * @dentry contains the dentry structure of new directory. | ||
| 382 | * @mode contains the mode of new directory. | ||
| 383 | * Return 0 if permission is granted. | ||
| 356 | * @inode_rmdir: | 384 | * @inode_rmdir: |
| 357 | * Check the permission to remove a directory. | 385 | * Check the permission to remove a directory. |
| 358 | * @dir contains the inode structure of parent of the directory to be removed. | 386 | * @dir contains the inode structure of parent of the directory to be removed. |
| 359 | * @dentry contains the dentry structure of directory to be removed. | 387 | * @dentry contains the dentry structure of directory to be removed. |
| 360 | * Return 0 if permission is granted. | 388 | * Return 0 if permission is granted. |
| 389 | * @path_rmdir: | ||
| 390 | * Check the permission to remove a directory. | ||
| 391 | * @dir contains the path structure of parent of the directory to be | ||
| 392 | * removed. | ||
| 393 | * @dentry contains the dentry structure of directory to be removed. | ||
| 394 | * Return 0 if permission is granted. | ||
| 361 | * @inode_mknod: | 395 | * @inode_mknod: |
| 362 | * Check permissions when creating a special file (or a socket or a fifo | 396 | * Check permissions when creating a special file (or a socket or a fifo |
| 363 | * file created via the mknod system call). Note that if mknod operation | 397 | * file created via the mknod system call). Note that if mknod operation |
| @@ -368,6 +402,15 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 368 | * @mode contains the mode of the new file. | 402 | * @mode contains the mode of the new file. |
| 369 | * @dev contains the device number. | 403 | * @dev contains the device number. |
| 370 | * Return 0 if permission is granted. | 404 | * Return 0 if permission is granted. |
| 405 | * @path_mknod: | ||
| 406 | * Check permissions when creating a file. Note that this hook is called | ||
| 407 | * even if mknod operation is being done for a regular file. | ||
| 408 | * @dir contains the path structure of parent of the new file. | ||
| 409 | * @dentry contains the dentry structure of the new file. | ||
| 410 | * @mode contains the mode of the new file. | ||
| 411 | * @dev contains the undecoded device number. Use new_decode_dev() to get | ||
| 412 | * the decoded device number. | ||
| 413 | * Return 0 if permission is granted. | ||
| 371 | * @inode_rename: | 414 | * @inode_rename: |
| 372 | * Check for permission to rename a file or directory. | 415 | * Check for permission to rename a file or directory. |
| 373 | * @old_dir contains the inode structure for parent of the old link. | 416 | * @old_dir contains the inode structure for parent of the old link. |
| @@ -375,6 +418,13 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 375 | * @new_dir contains the inode structure for parent of the new link. | 418 | * @new_dir contains the inode structure for parent of the new link. |
| 376 | * @new_dentry contains the dentry structure of the new link. | 419 | * @new_dentry contains the dentry structure of the new link. |
| 377 | * Return 0 if permission is granted. | 420 | * Return 0 if permission is granted. |
| 421 | * @path_rename: | ||
| 422 | * Check for permission to rename a file or directory. | ||
| 423 | * @old_dir contains the path structure for parent of the old link. | ||
| 424 | * @old_dentry contains the dentry structure of the old link. | ||
| 425 | * @new_dir contains the path structure for parent of the new link. | ||
| 426 | * @new_dentry contains the dentry structure of the new link. | ||
| 427 | * Return 0 if permission is granted. | ||
| 378 | * @inode_readlink: | 428 | * @inode_readlink: |
| 379 | * Check the permission to read the symbolic link. | 429 | * Check the permission to read the symbolic link. |
| 380 | * @dentry contains the dentry structure for the file link. | 430 | * @dentry contains the dentry structure for the file link. |
| @@ -403,6 +453,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 403 | * @dentry contains the dentry structure for the file. | 453 | * @dentry contains the dentry structure for the file. |
| 404 | * @attr is the iattr structure containing the new file attributes. | 454 | * @attr is the iattr structure containing the new file attributes. |
| 405 | * Return 0 if permission is granted. | 455 | * Return 0 if permission is granted. |
| 456 | * @path_truncate: | ||
| 457 | * Check permission before truncating a file. | ||
| 458 | * @path contains the path structure for the file. | ||
| 459 | * @length is the new length of the file. | ||
| 460 | * @time_attrs is the flags passed to do_truncate(). | ||
| 461 | * Return 0 if permission is granted. | ||
| 406 | * @inode_getattr: | 462 | * @inode_getattr: |
| 407 | * Check permission before obtaining file attributes. | 463 | * Check permission before obtaining file attributes. |
| 408 | * @mnt is the vfsmount where the dentry was looked up | 464 | * @mnt is the vfsmount where the dentry was looked up |
| @@ -1331,6 +1387,22 @@ struct security_operations { | |||
| 1331 | struct super_block *newsb); | 1387 | struct super_block *newsb); |
| 1332 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); | 1388 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); |
| 1333 | 1389 | ||
| 1390 | #ifdef CONFIG_SECURITY_PATH | ||
| 1391 | int (*path_unlink) (struct path *dir, struct dentry *dentry); | ||
| 1392 | int (*path_mkdir) (struct path *dir, struct dentry *dentry, int mode); | ||
| 1393 | int (*path_rmdir) (struct path *dir, struct dentry *dentry); | ||
| 1394 | int (*path_mknod) (struct path *dir, struct dentry *dentry, int mode, | ||
| 1395 | unsigned int dev); | ||
| 1396 | int (*path_truncate) (struct path *path, loff_t length, | ||
| 1397 | unsigned int time_attrs); | ||
| 1398 | int (*path_symlink) (struct path *dir, struct dentry *dentry, | ||
| 1399 | const char *old_name); | ||
| 1400 | int (*path_link) (struct dentry *old_dentry, struct path *new_dir, | ||
| 1401 | struct dentry *new_dentry); | ||
| 1402 | int (*path_rename) (struct path *old_dir, struct dentry *old_dentry, | ||
| 1403 | struct path *new_dir, struct dentry *new_dentry); | ||
| 1404 | #endif | ||
| 1405 | |||
| 1334 | int (*inode_alloc_security) (struct inode *inode); | 1406 | int (*inode_alloc_security) (struct inode *inode); |
| 1335 | void (*inode_free_security) (struct inode *inode); | 1407 | void (*inode_free_security) (struct inode *inode); |
| 1336 | int (*inode_init_security) (struct inode *inode, struct inode *dir, | 1408 | int (*inode_init_security) (struct inode *inode, struct inode *dir, |
| @@ -2705,6 +2777,71 @@ static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi | |||
| 2705 | 2777 | ||
| 2706 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 2778 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
| 2707 | 2779 | ||
| 2780 | #ifdef CONFIG_SECURITY_PATH | ||
| 2781 | int security_path_unlink(struct path *dir, struct dentry *dentry); | ||
| 2782 | int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode); | ||
| 2783 | int security_path_rmdir(struct path *dir, struct dentry *dentry); | ||
| 2784 | int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, | ||
| 2785 | unsigned int dev); | ||
| 2786 | int security_path_truncate(struct path *path, loff_t length, | ||
| 2787 | unsigned int time_attrs); | ||
| 2788 | int security_path_symlink(struct path *dir, struct dentry *dentry, | ||
| 2789 | const char *old_name); | ||
| 2790 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
| 2791 | struct dentry *new_dentry); | ||
| 2792 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | ||
| 2793 | struct path *new_dir, struct dentry *new_dentry); | ||
| 2794 | #else /* CONFIG_SECURITY_PATH */ | ||
| 2795 | static inline int security_path_unlink(struct path *dir, struct dentry *dentry) | ||
| 2796 | { | ||
| 2797 | return 0; | ||
| 2798 | } | ||
| 2799 | |||
| 2800 | static inline int security_path_mkdir(struct path *dir, struct dentry *dentry, | ||
| 2801 | int mode) | ||
| 2802 | { | ||
| 2803 | return 0; | ||
| 2804 | } | ||
| 2805 | |||
| 2806 | static inline int security_path_rmdir(struct path *dir, struct dentry *dentry) | ||
| 2807 | { | ||
| 2808 | return 0; | ||
| 2809 | } | ||
| 2810 | |||
| 2811 | static inline int security_path_mknod(struct path *dir, struct dentry *dentry, | ||
| 2812 | int mode, unsigned int dev) | ||
| 2813 | { | ||
| 2814 | return 0; | ||
| 2815 | } | ||
| 2816 | |||
| 2817 | static inline int security_path_truncate(struct path *path, loff_t length, | ||
| 2818 | unsigned int time_attrs) | ||
| 2819 | { | ||
| 2820 | return 0; | ||
| 2821 | } | ||
| 2822 | |||
| 2823 | static inline int security_path_symlink(struct path *dir, struct dentry *dentry, | ||
| 2824 | const char *old_name) | ||
| 2825 | { | ||
| 2826 | return 0; | ||
| 2827 | } | ||
| 2828 | |||
| 2829 | static inline int security_path_link(struct dentry *old_dentry, | ||
| 2830 | struct path *new_dir, | ||
| 2831 | struct dentry *new_dentry) | ||
| 2832 | { | ||
| 2833 | return 0; | ||
| 2834 | } | ||
| 2835 | |||
| 2836 | static inline int security_path_rename(struct path *old_dir, | ||
| 2837 | struct dentry *old_dentry, | ||
| 2838 | struct path *new_dir, | ||
| 2839 | struct dentry *new_dentry) | ||
| 2840 | { | ||
| 2841 | return 0; | ||
| 2842 | } | ||
| 2843 | #endif /* CONFIG_SECURITY_PATH */ | ||
| 2844 | |||
| 2708 | #ifdef CONFIG_KEYS | 2845 | #ifdef CONFIG_KEYS |
| 2709 | #ifdef CONFIG_SECURITY | 2846 | #ifdef CONFIG_SECURITY |
| 2710 | 2847 | ||
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index c6250d0055d2..d1b89820ab4f 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -836,7 +836,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 836 | err = mnt_want_write(nd.path.mnt); | 836 | err = mnt_want_write(nd.path.mnt); |
| 837 | if (err) | 837 | if (err) |
| 838 | goto out_mknod_dput; | 838 | goto out_mknod_dput; |
| 839 | err = security_path_mknod(&nd.path, dentry, mode, 0); | ||
| 840 | if (err) | ||
| 841 | goto out_mknod_drop_write; | ||
| 839 | err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); | 842 | err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); |
| 843 | out_mknod_drop_write: | ||
| 840 | mnt_drop_write(nd.path.mnt); | 844 | mnt_drop_write(nd.path.mnt); |
| 841 | if (err) | 845 | if (err) |
| 842 | goto out_mknod_dput; | 846 | goto out_mknod_dput; |
diff --git a/security/Kconfig b/security/Kconfig index d9f47ce7e207..9438535d7fd0 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
| @@ -81,6 +81,15 @@ config SECURITY_NETWORK_XFRM | |||
| 81 | IPSec. | 81 | IPSec. |
| 82 | If you are unsure how to answer this question, answer N. | 82 | If you are unsure how to answer this question, answer N. |
| 83 | 83 | ||
| 84 | config SECURITY_PATH | ||
| 85 | bool "Security hooks for pathname based access control" | ||
| 86 | depends on SECURITY | ||
| 87 | help | ||
| 88 | This enables the security hooks for pathname based access control. | ||
| 89 | If enabled, a security module can use these hooks to | ||
| 90 | implement pathname based access controls. | ||
| 91 | If you are unsure how to answer this question, answer N. | ||
| 92 | |||
| 84 | config SECURITY_FILE_CAPABILITIES | 93 | config SECURITY_FILE_CAPABILITIES |
| 85 | bool "File POSIX Capabilities" | 94 | bool "File POSIX Capabilities" |
| 86 | default n | 95 | default n |
diff --git a/security/capability.c b/security/capability.c index 2dce66fcb992..c545bd1300b5 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -263,6 +263,53 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid) | |||
| 263 | *secid = 0; | 263 | *secid = 0; |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | #ifdef CONFIG_SECURITY_PATH | ||
| 267 | static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode, | ||
| 268 | unsigned int dev) | ||
| 269 | { | ||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | static int cap_path_mkdir(struct path *dir, struct dentry *dentry, int mode) | ||
| 274 | { | ||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | |||
| 278 | static int cap_path_rmdir(struct path *dir, struct dentry *dentry) | ||
| 279 | { | ||
| 280 | return 0; | ||
| 281 | } | ||
| 282 | |||
| 283 | static int cap_path_unlink(struct path *dir, struct dentry *dentry) | ||
| 284 | { | ||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int cap_path_symlink(struct path *dir, struct dentry *dentry, | ||
| 289 | const char *old_name) | ||
| 290 | { | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int cap_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
| 295 | struct dentry *new_dentry) | ||
| 296 | { | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | |||
| 300 | static int cap_path_rename(struct path *old_path, struct dentry *old_dentry, | ||
| 301 | struct path *new_path, struct dentry *new_dentry) | ||
| 302 | { | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | static int cap_path_truncate(struct path *path, loff_t length, | ||
| 307 | unsigned int time_attrs) | ||
| 308 | { | ||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | #endif | ||
| 312 | |||
| 266 | static int cap_file_permission(struct file *file, int mask) | 313 | static int cap_file_permission(struct file *file, int mask) |
| 267 | { | 314 | { |
| 268 | return 0; | 315 | return 0; |
| @@ -883,6 +930,16 @@ void security_fixup_ops(struct security_operations *ops) | |||
| 883 | set_to_cap_if_null(ops, inode_setsecurity); | 930 | set_to_cap_if_null(ops, inode_setsecurity); |
| 884 | set_to_cap_if_null(ops, inode_listsecurity); | 931 | set_to_cap_if_null(ops, inode_listsecurity); |
| 885 | set_to_cap_if_null(ops, inode_getsecid); | 932 | set_to_cap_if_null(ops, inode_getsecid); |
| 933 | #ifdef CONFIG_SECURITY_PATH | ||
| 934 | set_to_cap_if_null(ops, path_mknod); | ||
| 935 | set_to_cap_if_null(ops, path_mkdir); | ||
| 936 | set_to_cap_if_null(ops, path_rmdir); | ||
| 937 | set_to_cap_if_null(ops, path_unlink); | ||
| 938 | set_to_cap_if_null(ops, path_symlink); | ||
| 939 | set_to_cap_if_null(ops, path_link); | ||
| 940 | set_to_cap_if_null(ops, path_rename); | ||
| 941 | set_to_cap_if_null(ops, path_truncate); | ||
| 942 | #endif | ||
| 886 | set_to_cap_if_null(ops, file_permission); | 943 | set_to_cap_if_null(ops, file_permission); |
| 887 | set_to_cap_if_null(ops, file_alloc_security); | 944 | set_to_cap_if_null(ops, file_alloc_security); |
| 888 | set_to_cap_if_null(ops, file_free_security); | 945 | set_to_cap_if_null(ops, file_free_security); |
diff --git a/security/security.c b/security/security.c index d85dbb37c972..678d4d07b852 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -355,6 +355,72 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 355 | } | 355 | } |
| 356 | EXPORT_SYMBOL(security_inode_init_security); | 356 | EXPORT_SYMBOL(security_inode_init_security); |
| 357 | 357 | ||
| 358 | #ifdef CONFIG_SECURITY_PATH | ||
| 359 | int security_path_mknod(struct path *path, struct dentry *dentry, int mode, | ||
| 360 | unsigned int dev) | ||
| 361 | { | ||
| 362 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 363 | return 0; | ||
| 364 | return security_ops->path_mknod(path, dentry, mode, dev); | ||
| 365 | } | ||
| 366 | EXPORT_SYMBOL(security_path_mknod); | ||
| 367 | |||
| 368 | int security_path_mkdir(struct path *path, struct dentry *dentry, int mode) | ||
| 369 | { | ||
| 370 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 371 | return 0; | ||
| 372 | return security_ops->path_mkdir(path, dentry, mode); | ||
| 373 | } | ||
| 374 | |||
| 375 | int security_path_rmdir(struct path *path, struct dentry *dentry) | ||
| 376 | { | ||
| 377 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 378 | return 0; | ||
| 379 | return security_ops->path_rmdir(path, dentry); | ||
| 380 | } | ||
| 381 | |||
| 382 | int security_path_unlink(struct path *path, struct dentry *dentry) | ||
| 383 | { | ||
| 384 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 385 | return 0; | ||
| 386 | return security_ops->path_unlink(path, dentry); | ||
| 387 | } | ||
| 388 | |||
| 389 | int security_path_symlink(struct path *path, struct dentry *dentry, | ||
| 390 | const char *old_name) | ||
| 391 | { | ||
| 392 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 393 | return 0; | ||
| 394 | return security_ops->path_symlink(path, dentry, old_name); | ||
| 395 | } | ||
| 396 | |||
| 397 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
| 398 | struct dentry *new_dentry) | ||
| 399 | { | ||
| 400 | if (unlikely(IS_PRIVATE(old_dentry->d_inode))) | ||
| 401 | return 0; | ||
| 402 | return security_ops->path_link(old_dentry, new_dir, new_dentry); | ||
| 403 | } | ||
| 404 | |||
| 405 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | ||
| 406 | struct path *new_dir, struct dentry *new_dentry) | ||
| 407 | { | ||
| 408 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || | ||
| 409 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) | ||
| 410 | return 0; | ||
| 411 | return security_ops->path_rename(old_dir, old_dentry, new_dir, | ||
| 412 | new_dentry); | ||
| 413 | } | ||
| 414 | |||
| 415 | int security_path_truncate(struct path *path, loff_t length, | ||
| 416 | unsigned int time_attrs) | ||
| 417 | { | ||
| 418 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 419 | return 0; | ||
| 420 | return security_ops->path_truncate(path, length, time_attrs); | ||
| 421 | } | ||
| 422 | #endif | ||
| 423 | |||
| 358 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) | 424 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) |
| 359 | { | 425 | { |
| 360 | if (unlikely(IS_PRIVATE(dir))) | 426 | if (unlikely(IS_PRIVATE(dir))) |
