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))) |