lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20080501055543.269648000@nttdata.co.jp>
Date:	Thu, 01 May 2008 14:54:06 +0900
From:	Toshiharu Harada <haradats@...data.co.jp>
To:	akpm@...ux-foundation.org, chrisw@...s-sol.org,
	viro@...IV.linux.org.uk
Cc:	linux-security-module@...r.kernel.org,
	linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org,
	Kentaro Takeda <takedakn@...data.co.jp>,
	Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>,
	Toshiharu Harada <haradats@...data.co.jp>
Subject: [TOMOYO #8 (2.6.25-mm1) 1/7] Introduce new LSM hooks.

This patch allows LSM to check permission using "struct vfsmount"
without passing "struct vfsmount" to VFS helper functions.

Signed-off-by: Kentaro Takeda <takedakn@...data.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@...data.co.jp>
---
 fs/exec.c                |   10 ++
 fs/namei.c               |  129 +++++++++++++++++++++++++++++++---
 fs/open.c                |    7 +
 include/linux/fs.h       |    8 ++
 include/linux/security.h |  178 +++++++++++++++++++++++++++++++++++++++++++++++
 net/unix/af_unix.c       |    4 +
 security/dummy.c         |   73 +++++++++++++++++++
 security/security.c      |   63 ++++++++++++++++
 8 files changed, 462 insertions(+), 10 deletions(-)

--- mm.orig/fs/exec.c
+++ mm/fs/exec.c
@@ -119,6 +119,16 @@ asmlinkage long sys_uselib(const char __
 	if (error)
 		goto exit;
 
+	/*
+	 * sys_access() with both R_OK and X_OK flags makes LSM's
+	 * security_inode_permission() unable to tell whether the request is
+	 * "just checking for permissions" or "actually loading a shared
+	 * library".
+	 */
+	error = security_path_uselib(&nd);
+	if (error)
+		goto exit;
+
 	file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
 	error = PTR_ERR(file);
 	if (IS_ERR(file))
--- mm.orig/fs/namei.c
+++ mm/fs/namei.c
@@ -1595,6 +1595,9 @@ int vfs_create(struct inode *dir, struct
 	error = security_inode_create(dir, dentry, mode);
 	if (error)
 		return error;
+	error = security_path_create(dir, dentry, mode, nd);
+	if (error)
+		return error;
 	DQUOT_INIT(dir);
 	error = dir->i_op->create(dir, dentry, mode, nd);
 	if (!error)
@@ -1650,6 +1653,17 @@ int may_open(struct nameidata *nd, int a
 			return -EPERM;
 
 	/*
+	 * security_inode_permission() called from vfs_permission()
+	 * can't know that the file is going to be truncated when
+	 * open(filename, O_WRONLY | O_TRUNC | O_APPEND) is used.
+	 * So, this hook checks O_APPEND and O_TRUNC flags as well
+	 * as MAY_READ and MAY_WRITE flags.
+	 */
+	error = security_path_open(nd->path.dentry, nd->path.mnt, flag);
+	if (error)
+		return error;
+
+	/*
 	 * Ensure there are no outstanding leases on the file.
 	 */
 	error = break_lease(inode, flag);
@@ -2021,7 +2035,12 @@ fail:
 }
 EXPORT_SYMBOL_GPL(lookup_create);
 
-int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+/*
+ * These pre_vfs_*() functions are separated from vfs_*() functions so that
+ * LSM's security_path_*() functions can do DAC checks before MAC checks
+ * without duplicating may_create()/may_delete() functions.
+ */
+int pre_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode)
 {
 	int error = may_create(dir, dentry, NULL);
 
@@ -2033,6 +2052,14 @@ int vfs_mknod(struct inode *dir, struct 
 
 	if (!dir->i_op || !dir->i_op->mknod)
 		return -EPERM;
+	return 0;
+}
+
+int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+{
+	int error = pre_vfs_mknod(dir, dentry, mode);
+	if (error)
+		return error;
 
 	error = devcgroup_inode_mknod(mode, dev);
 	if (error)
@@ -2096,6 +2123,9 @@ asmlinkage long sys_mknodat(int dfd, con
 	error = mnt_want_write(nd.path.mnt);
 	if (error)
 		goto out_dput;
+	error = security_path_mknod(&nd.path, dentry, mode, dev);
+	if (error)
+		goto out_drop_write;
 	switch (mode & S_IFMT) {
 		case 0: case S_IFREG:
 			error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
@@ -2108,6 +2138,7 @@ asmlinkage long sys_mknodat(int dfd, con
 			error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
 			break;
 	}
+out_drop_write:
 	mnt_drop_write(nd.path.mnt);
 out_dput:
 	dput(dentry);
@@ -2125,7 +2156,7 @@ asmlinkage long sys_mknod(const char __u
 	return sys_mknodat(AT_FDCWD, filename, mode, dev);
 }
 
-int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+int pre_vfs_mkdir(struct inode *dir, struct dentry *dentry)
 {
 	int error = may_create(dir, dentry, NULL);
 
@@ -2134,6 +2165,14 @@ int vfs_mkdir(struct inode *dir, struct 
 
 	if (!dir->i_op || !dir->i_op->mkdir)
 		return -EPERM;
+	return 0;
+}
+
+int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int error = pre_vfs_mkdir(dir, dentry);
+	if (error)
+		return error;
 
 	mode &= (S_IRWXUGO|S_ISVTX);
 	error = security_inode_mkdir(dir, dentry, mode);
@@ -2172,7 +2211,11 @@ asmlinkage long sys_mkdirat(int dfd, con
 	error = mnt_want_write(nd.path.mnt);
 	if (error)
 		goto out_dput;
+	error = security_path_mkdir(&nd.path, dentry, mode);
+	if (error)
+		goto out_drop_write;
 	error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
+out_drop_write:
 	mnt_drop_write(nd.path.mnt);
 out_dput:
 	dput(dentry);
@@ -2217,7 +2260,7 @@ void dentry_unhash(struct dentry *dentry
 	spin_unlock(&dcache_lock);
 }
 
-int vfs_rmdir(struct inode *dir, struct dentry *dentry)
+int pre_vfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error = may_delete(dir, dentry, 1);
 
@@ -2226,6 +2269,14 @@ int vfs_rmdir(struct inode *dir, struct 
 
 	if (!dir->i_op || !dir->i_op->rmdir)
 		return -EPERM;
+	return 0;
+}
+
+int vfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	int error = pre_vfs_rmdir(dir, dentry);
+	if (error)
+		return error;
 
 	DQUOT_INIT(dir);
 
@@ -2284,7 +2335,11 @@ static long do_rmdir(int dfd, const char
 	error = mnt_want_write(nd.path.mnt);
 	if (error)
 		goto exit3;
+	error = security_path_rmdir(&nd.path, dentry);
+	if (error)
+		goto exit4;
 	error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
+exit4:
 	mnt_drop_write(nd.path.mnt);
 exit3:
 	dput(dentry);
@@ -2302,7 +2357,7 @@ asmlinkage long sys_rmdir(const char __u
 	return do_rmdir(AT_FDCWD, pathname);
 }
 
-int vfs_unlink(struct inode *dir, struct dentry *dentry)
+int pre_vfs_unlink(struct inode *dir, struct dentry *dentry)
 {
 	int error = may_delete(dir, dentry, 0);
 
@@ -2311,6 +2366,14 @@ int vfs_unlink(struct inode *dir, struct
 
 	if (!dir->i_op || !dir->i_op->unlink)
 		return -EPERM;
+	return 0;
+}
+
+int vfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	int error = pre_vfs_unlink(dir, dentry);
+	if (error)
+		return error;
 
 	DQUOT_INIT(dir);
 
@@ -2370,7 +2433,11 @@ static long do_unlinkat(int dfd, const c
 		error = mnt_want_write(nd.path.mnt);
 		if (error)
 			goto exit2;
+		error = security_path_unlink(&nd.path, dentry);
+		if (error)
+			goto exit3;
 		error = vfs_unlink(nd.path.dentry->d_inode, dentry);
+exit3:
 		mnt_drop_write(nd.path.mnt);
 	exit2:
 		dput(dentry);
@@ -2406,7 +2473,7 @@ asmlinkage long sys_unlink(const char __
 	return do_unlinkat(AT_FDCWD, pathname);
 }
 
-int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
+int pre_vfs_symlink(struct inode *dir, struct dentry *dentry)
 {
 	int error = may_create(dir, dentry, NULL);
 
@@ -2415,6 +2482,15 @@ int vfs_symlink(struct inode *dir, struc
 
 	if (!dir->i_op || !dir->i_op->symlink)
 		return -EPERM;
+	return 0;
+}
+
+int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname,
+		int mode)
+{
+	int error = pre_vfs_symlink(dir, dentry);
+	if (error)
+		return error;
 
 	error = security_inode_symlink(dir, dentry, oldname);
 	if (error)
@@ -2455,7 +2531,11 @@ asmlinkage long sys_symlinkat(const char
 	error = mnt_want_write(nd.path.mnt);
 	if (error)
 		goto out_dput;
+	error = security_path_symlink(&nd.path, dentry, from);
+	if (error)
+		goto out_drop_write;
 	error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO);
+out_drop_write:
 	mnt_drop_write(nd.path.mnt);
 out_dput:
 	dput(dentry);
@@ -2474,7 +2554,8 @@ asmlinkage long sys_symlink(const char _
 	return sys_symlinkat(oldname, AT_FDCWD, newname);
 }
 
-int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
+int pre_vfs_link(struct dentry *old_dentry, struct inode *dir,
+		 struct dentry *new_dentry)
 {
 	struct inode *inode = old_dentry->d_inode;
 	int error;
@@ -2498,6 +2579,15 @@ int vfs_link(struct dentry *old_dentry, 
 		return -EPERM;
 	if (S_ISDIR(old_dentry->d_inode->i_mode))
 		return -EPERM;
+	return 0;
+}
+
+int vfs_link(struct dentry *old_dentry, struct inode *dir,
+	     struct dentry *new_dentry)
+{
+	int error = pre_vfs_link(old_dentry, dir, new_dentry);
+	if (error)
+		return error;
 
 	error = security_inode_link(old_dentry, dir, new_dentry);
 	if (error)
@@ -2555,7 +2645,11 @@ asmlinkage long sys_linkat(int olddfd, c
 	error = mnt_want_write(nd.path.mnt);
 	if (error)
 		goto out_dput;
+	error = security_path_link(&old_nd.path, &nd.path, new_dentry);
+	if (error)
+		goto out_drop_write;
 	error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry);
+out_drop_write:
 	mnt_drop_write(nd.path.mnt);
 out_dput:
 	dput(new_dentry);
@@ -2679,16 +2773,15 @@ static int vfs_rename_other(struct inode
 	return error;
 }
 
-int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-	       struct inode *new_dir, struct dentry *new_dentry)
+int pre_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+		   struct inode *new_dir, struct dentry *new_dentry)
 {
 	int error;
 	int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
-	const char *old_name;
 
 	if (old_dentry->d_inode == new_dentry->d_inode)
  		return 0;
- 
+
 	error = may_delete(old_dir, old_dentry, is_dir);
 	if (error)
 		return error;
@@ -2702,6 +2795,17 @@ int vfs_rename(struct inode *old_dir, st
 
 	if (!old_dir->i_op || !old_dir->i_op->rename)
 		return -EPERM;
+	return 0;
+}
+
+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+	       struct inode *new_dir, struct dentry *new_dentry)
+{
+	int error = pre_vfs_rename(old_dir, old_dentry, new_dir, new_dentry);
+	int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
+	const char *old_name;
+	if (error)
+		return error;
 
 	DQUOT_INIT(old_dir);
 	DQUOT_INIT(new_dir);
@@ -2786,8 +2890,13 @@ static int do_rename(int olddfd, const c
 	error = mnt_want_write(oldnd.path.mnt);
 	if (error)
 		goto exit5;
+	error = security_path_rename(&oldnd.path, old_dentry,
+				     &newnd.path, new_dentry);
+	if (error)
+		goto exit6;
 	error = vfs_rename(old_dir->d_inode, old_dentry,
 				   new_dir->d_inode, new_dentry);
+exit6:
 	mnt_drop_write(oldnd.path.mnt);
 exit5:
 	dput(new_dentry);
--- mm.orig/fs/open.c
+++ mm/fs/open.c
@@ -268,6 +268,9 @@ static long do_sys_truncate(const char _
 	if (error)
 		goto put_write_and_out;
 
+	error = security_path_truncate(&nd.path, length, 0, NULL);
+	if (error)
+		goto put_write_and_out;
 	error = locks_verify_truncate(inode, NULL, length);
 	if (!error) {
 		DQUOT_INIT(inode);
@@ -324,6 +327,10 @@ static long do_sys_ftruncate(unsigned in
 	if (IS_APPEND(inode))
 		goto out_putf;
 
+	error = security_path_truncate(&file->f_path, length,
+				       ATTR_MTIME|ATTR_CTIME, file);
+	if (error)
+		goto out_putf;
 	error = locks_verify_truncate(inode, file, length);
 	if (!error)
 		error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
--- mm.orig/include/linux/fs.h
+++ mm/include/linux/fs.h
@@ -1124,12 +1124,20 @@ extern void unlock_super(struct super_bl
  */
 extern int vfs_permission(struct nameidata *, int);
 extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
+extern int pre_vfs_mkdir(struct inode *, struct dentry *);
 extern int vfs_mkdir(struct inode *, struct dentry *, int);
+extern int pre_vfs_mknod(struct inode *, struct dentry *, int);
 extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
+extern int pre_vfs_symlink(struct inode *, struct dentry *);
 extern int vfs_symlink(struct inode *, struct dentry *, const char *, int);
+extern int pre_vfs_link(struct dentry *, struct inode *, struct dentry *);
 extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
+extern int pre_vfs_rmdir(struct inode *, struct dentry *);
 extern int vfs_rmdir(struct inode *, struct dentry *);
+extern int pre_vfs_unlink(struct inode *, struct dentry *);
 extern int vfs_unlink(struct inode *, struct dentry *);
+extern int pre_vfs_rename(struct inode *, struct dentry *, struct inode *,
+			  struct dentry *);
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 
 /*
--- mm.orig/include/linux/security.h
+++ mm/include/linux/security.h
@@ -343,23 +343,50 @@ static inline void security_free_mnt_opt
  *	@dentry contains the dentry structure for the file to be created.
  *	@mode contains the file mode of the file to be created.
  *	Return 0 if permission is granted.
+ * @path_create:
+ *	Check permission to create a regular file.
+ *	@dir contains inode structure of the parent of the new file.
+ *	@dentry contains the dentry structure for the file to be created.
+ *	@mode contains the file mode of the file to be created.
+ *	@nd contains the nameidata structure (may be NULL).
+ *	Return 0 if permission is granted.
  * @inode_link:
  *	Check permission before creating a new hard link to a file.
  *	@old_dentry contains the dentry structure for an existing link to the file.
  *	@dir contains the inode structure of the parent directory of the new link.
  *	@new_dentry contains the dentry structure for the new link.
  *	Return 0 if permission is granted.
+ * @path_link:
+ *	Check permission before creating a new hard link to a file.
+ *	@old_path contains the path structure for an existing link
+ *	to the file.
+ *	@new_dir contains the path structure of the parent directory of
+ *	the new link.
+ *	@new_dentry contains the dentry structure for the new link.
+ *	Return 0 if permission is granted.
  * @inode_unlink:
  *	Check the permission to remove a hard link to a file. 
  *	@dir contains the inode structure of parent directory of the file.
  *	@dentry contains the dentry structure for file to be unlinked.
  *	Return 0 if permission is granted.
+ * @path_unlink:
+ *	Check the permission to remove a hard link to a file.
+ *	@dir contains the path structure of parent directory of the file.
+ *	@dentry contains the dentry structure for file to be unlinked.
+ *	Return 0 if permission is granted.
  * @inode_symlink:
  *	Check the permission to create a symbolic link to a file.
  *	@dir contains the inode structure of parent directory of the symbolic link.
  *	@dentry contains the dentry structure of the symbolic link.
  *	@old_name contains the pathname of file.
  *	Return 0 if permission is granted.
+ * @path_symlink:
+ *	Check the permission to create a symbolic link to a file.
+ *	@dir contains the path structure of parent directory of
+ *	the symbolic link.
+ *	@dentry contains the dentry structure of the symbolic link.
+ *	@old_name contains the pathname of file.
+ *	Return 0 if permission is granted.
  * @inode_mkdir:
  *	Check permissions to create a new directory in the existing directory
  *	associated with inode strcture @dir. 
@@ -367,11 +394,25 @@ static inline void security_free_mnt_opt
  *	@dentry contains the dentry structure of new directory.
  *	@mode contains the mode of new directory.
  *	Return 0 if permission is granted.
+ * @path_mkdir:
+ *	Check permissions to create a new directory in the existing directory
+ *	associated with path strcture @path.
+ *	@dir containst the path structure of parent of the directory
+ *	to be created.
+ *	@dentry contains the dentry structure of new directory.
+ *	@mode contains the mode of new directory.
+ *	Return 0 if permission is granted.
  * @inode_rmdir:
  *	Check the permission to remove a directory.
  *	@dir contains the inode structure of parent of the directory to be removed.
  *	@dentry contains the dentry structure of directory to be removed.
  *	Return 0 if permission is granted.
+ * @path_rmdir:
+ *	Check the permission to remove a directory.
+ *	@dir contains the path structure of parent of the directory to be
+ *	removed.
+ *	@dentry contains the dentry structure of directory to be removed.
+ *	Return 0 if permission is granted.
  * @inode_mknod:
  *	Check permissions when creating a special file (or a socket or a fifo
  *	file created via the mknod system call).  Note that if mknod operation
@@ -382,6 +423,15 @@ static inline void security_free_mnt_opt
  *	@mode contains the mode of the new file.
  *	@dev contains the device number.
  *	Return 0 if permission is granted.
+ * @path_mknod:
+ *	Check permissions when creating a file. Note that this hook is called
+ *	even if mknod operation is being done for a regular file.
+ *	@dir contains the path structure of parent of the new file.
+ *	@dentry contains the dentry structure of the new file.
+ *	@mode contains the mode of the new file.
+ *	@dev contains the undecoded device number. Use new_decode_dev() to get
+ *	the decoded device number.
+ *	Return 0 if permission is granted.
  * @inode_rename:
  *	Check for permission to rename a file or directory.
  *	@old_dir contains the inode structure for parent of the old link.
@@ -389,6 +439,13 @@ static inline void security_free_mnt_opt
  *	@new_dir contains the inode structure for parent of the new link.
  *	@new_dentry contains the dentry structure of the new link.
  *	Return 0 if permission is granted.
+ * @path_rename:
+ *	Check for permission to rename a file or directory.
+ *	@old_dir contains the path structure for parent of the old link.
+ *	@old_dentry contains the dentry structure of the old link.
+ *	@new_dir contains the path structure for parent of the new link.
+ *	@new_dentry contains the dentry structure of the new link.
+ *	Return 0 if permission is granted.
  * @inode_readlink:
  *	Check the permission to read the symbolic link.
  *	@dentry contains the dentry structure for the file link.
@@ -409,6 +466,12 @@ static inline void security_free_mnt_opt
  *	@mask contains the permission mask.
  *     @nd contains the nameidata (may be NULL).
  *	Return 0 if permission is granted.
+ * @path_open:
+ *	Check permission to open a file.
+ *	@dentry contains the dentry structure for the file to be opened.
+ *	@mnt contains the vfsmount structure for the file to be opened.
+ *	@flags contains the open flags.
+ *	Return 0 if permission is granted.
  * @inode_setattr:
  *	Check permission before setting file attributes.  Note that the kernel
  *	call to notify_change is performed from several locations, whenever
@@ -417,6 +480,17 @@ static inline void security_free_mnt_opt
  *	@dentry contains the dentry structure for the file.
  *	@attr is the iattr structure containing the new file attributes.
  *	Return 0 if permission is granted.
+ * @path_truncate:
+ *	Check permission before truncating a file.
+ *	@path contains the path structure for the file.
+ *	@length is the new length of the file.
+ *	@time_attrs is the flags passed to do_truncate().
+ *	@filp is the file structure (may be NULL).
+ *	Return 0 if permission is granted.
+ * @path_uselib:
+ *      Check permission before using a library.
+ *      @nd contains the nameidata.
+ *      Return 0 if permission is granted.
  * @inode_getattr:
  *	Check permission before obtaining file attributes.
  *	@mnt is the vfsmount where the dentry was looked up
@@ -1351,6 +1425,25 @@ struct security_operations {
 				   struct super_block *newsb);
 	int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
 
+	int (*path_create) (struct inode *dir, struct dentry *dentry, int mode,
+			    struct nameidata *nd);
+	int (*path_unlink) (struct path *dir, struct dentry *dentry);
+	int (*path_mkdir) (struct path *dir, struct dentry *dentry, int mode);
+	int (*path_rmdir) (struct path *dir, struct dentry *dentry);
+	int (*path_mknod) (struct path *dir, struct dentry *dentry, int mode,
+			   unsigned int dev);
+	int (*path_truncate) (struct path *path, loff_t length,
+			      unsigned int time_attrs, struct file *filp);
+	int (*path_uselib) (struct nameidata *nd);
+	int (*path_symlink) (struct path *dir, struct dentry *dentry,
+			     const char *old_name);
+	int (*path_link) (struct path *old_path, struct path *new_dir,
+			  struct dentry *new_dentry);
+	int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
+			    struct path *new_dir, struct dentry *new_dentry);
+	int (*path_open) (struct dentry *dentry, struct vfsmount *mnt,
+			  int flags);
+
 	int (*inode_alloc_security) (struct inode *inode);	
 	void (*inode_free_security) (struct inode *inode);
 	int (*inode_init_security) (struct inode *inode, struct inode *dir,
@@ -1625,6 +1718,24 @@ void security_sb_clone_mnt_opts(const st
 				struct super_block *newsb);
 int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
 
+int security_path_create(struct inode *dir, struct dentry *dentry, int mode,
+			 struct nameidata *nd);
+int security_path_unlink(struct path *dir, struct dentry *dentry);
+int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode);
+int security_path_rmdir(struct path *dir, struct dentry *dentry);
+int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
+			unsigned int dev);
+int security_path_truncate(struct path *path, loff_t length,
+			   unsigned int time_attrs, struct file *filp);
+int security_path_uselib(struct nameidata *nd);
+int security_path_symlink(struct path *dir, struct dentry *dentry,
+			  const char *old_name);
+int security_path_link(struct path *old_path, struct path *new_dir,
+		       struct dentry *new_dentry);
+int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+			 struct path *new_dir, struct dentry *new_dentry);
+int security_path_open(struct dentry *dentry, struct vfsmount *mnt, int flags);
+
 int security_inode_alloc(struct inode *inode);
 void security_inode_free(struct inode *inode);
 int security_inode_init_security(struct inode *inode, struct inode *dir,
@@ -1950,6 +2061,73 @@ static inline int security_sb_parse_opts
 	return 0;
 }
 
+static inline int security_path_create(struct inode *dir, struct dentry *dentry,
+				       int mode, struct nameidata *nd)
+{
+	return 0;
+}
+static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
+{
+	return 0;
+}
+
+static inline int security_path_mkdir(struct path *dir, struct dentry *dentry,
+				      int mode)
+{
+	return 0;
+}
+
+static inline int security_path_rmdir(struct path *dir, struct dentry *dentry)
+{
+	return 0;
+}
+
+static inline int security_path_mknod(struct path *dir, struct dentry *dentry,
+				      int mode, unsigned int dev)
+{
+	return 0;
+}
+
+static inline int security_path_truncate(struct path *path, loff_t length,
+					 unsigned int time_attrs,
+					 struct file *filp)
+{
+	return 0;
+}
+
+static inline int security_path_uselib(struct nameidata *nd)
+{
+	return 0;
+}
+
+static inline int security_path_symlink(struct path *dir, struct dentry *dentry,
+					const char *old_name)
+{
+	return 0;
+}
+
+static inline int security_path_link(struct path *old_path,
+				     struct path *new_dir,
+				     struct dentry *new_dentry)
+{
+	return 0;
+}
+
+static inline int security_path_rename(struct path *old_dir,
+				       struct dentry *old_dentry,
+				       struct path *new_dir,
+				       struct dentry *new_dentry)
+{
+	return 0;
+}
+
+static inline int security_path_open(struct dentry *dentry,
+				     struct vfsmount *mnt,
+				     int flags)
+{
+	return 0;
+}
+
 static inline int security_inode_alloc (struct inode *inode)
 {
 	return 0;
--- mm.orig/net/unix/af_unix.c
+++ mm/net/unix/af_unix.c
@@ -822,7 +822,11 @@ static int unix_bind(struct socket *sock
 		err = mnt_want_write(nd.path.mnt);
 		if (err)
 			goto out_mknod_dput;
+		err = security_path_mknod(&nd.path, dentry, mode, 0);
+		if (err)
+			goto out_drop_write;
 		err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
+out_drop_write:
 		mnt_drop_write(nd.path.mnt);
 		if (err)
 			goto out_mknod_dput;
--- mm.orig/security/dummy.c
+++ mm/security/dummy.c
@@ -270,6 +270,68 @@ static int dummy_sb_parse_opts_str(char 
 	return 0;
 }
 
+static int dummy_path_create(struct inode *inode, struct dentry *dentry,
+			     int mask, struct nameidata *nd)
+{
+	return 0;
+}
+
+static int dummy_path_mknod(struct path *dir, struct dentry *dentry, int mode,
+			    unsigned int dev)
+{
+	return 0;
+}
+
+static int dummy_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
+{
+	return 0;
+}
+
+static int dummy_path_rmdir(struct path *dir, struct dentry *dentry)
+{
+	return 0;
+}
+
+static int dummy_path_unlink(struct path *dir, struct dentry *dentry)
+{
+	return 0;
+}
+
+static int dummy_path_symlink(struct path *dir, struct dentry *dentry,
+			      const char *old_name)
+{
+	return 0;
+}
+
+static int dummy_path_link(struct path *old_path, struct path *new_dir,
+			   struct dentry *new_dentry)
+{
+	return 0;
+}
+
+static int dummy_path_rename(struct path *old_path, struct dentry *old_dentry,
+			     struct path *new_path, struct dentry *new_dentry)
+{
+	return 0;
+}
+
+static int dummy_path_open(struct dentry *dentry, struct vfsmount *mnt,
+			   int flags)
+{
+	return 0;
+}
+
+static int dummy_path_truncate(struct path *path, loff_t length,
+			       unsigned int time_attrs, struct file *filp)
+{
+	return 0;
+}
+
+static int dummy_path_uselib(struct nameidata *nd)
+{
+	return 0;
+}
+
 static int dummy_inode_alloc_security (struct inode *inode)
 {
 	return 0;
@@ -1079,6 +1141,17 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, sb_set_mnt_opts);
 	set_to_dummy_if_null(ops, sb_clone_mnt_opts);
 	set_to_dummy_if_null(ops, sb_parse_opts_str);
+	set_to_dummy_if_null(ops, path_create);
+	set_to_dummy_if_null(ops, path_mknod);
+	set_to_dummy_if_null(ops, path_mkdir);
+	set_to_dummy_if_null(ops, path_rmdir);
+	set_to_dummy_if_null(ops, path_unlink);
+	set_to_dummy_if_null(ops, path_symlink);
+	set_to_dummy_if_null(ops, path_link);
+	set_to_dummy_if_null(ops, path_rename);
+	set_to_dummy_if_null(ops, path_open);
+	set_to_dummy_if_null(ops, path_truncate);
+	set_to_dummy_if_null(ops, path_uselib);
 	set_to_dummy_if_null(ops, inode_alloc_security);
 	set_to_dummy_if_null(ops, inode_free_security);
 	set_to_dummy_if_null(ops, inode_init_security);
--- mm.orig/security/security.c
+++ mm/security/security.c
@@ -388,6 +388,69 @@ int security_inode_init_security(struct 
 }
 EXPORT_SYMBOL(security_inode_init_security);
 
+int security_path_create(struct inode *dir, struct dentry *dentry, int mode,
+			 struct nameidata *nd)
+{
+	if (unlikely(IS_PRIVATE(dir)))
+		return 0;
+	return security_ops->path_create(dir, dentry, mode, nd);
+}
+int security_path_mknod(struct path *path, struct dentry *dentry, int mode,
+			unsigned int dev)
+{
+	return security_ops->path_mknod(path, dentry, mode, dev);
+}
+
+int security_path_mkdir(struct path *path, struct dentry *dentry, int mode)
+{
+	return security_ops->path_mkdir(path, dentry, mode);
+}
+
+int security_path_rmdir(struct path *path, struct dentry *dentry)
+{
+	return security_ops->path_rmdir(path, dentry);
+}
+
+int security_path_unlink(struct path *path, struct dentry *dentry)
+{
+	return security_ops->path_unlink(path, dentry);
+}
+
+int security_path_symlink(struct path *path, struct dentry *dentry,
+			  const char *old_name)
+{
+	return security_ops->path_symlink(path, dentry, old_name);
+}
+
+int security_path_link(struct path *old_path, struct path *new_dir,
+		       struct dentry *new_dentry)
+{
+	return security_ops->path_link(old_path, new_dir, new_dentry);
+}
+
+int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+			 struct path *new_dir, struct dentry *new_dentry)
+{
+	return security_ops->path_rename(old_dir, old_dentry, new_dir,
+					 new_dentry);
+}
+
+int security_path_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
+{
+	return security_ops->path_open(dentry, mnt, flags);
+}
+
+int security_path_truncate(struct path *path, loff_t length,
+			   unsigned int time_attrs, struct file *filp)
+{
+	return security_ops->path_truncate(path, length, time_attrs, filp);
+}
+
+int security_path_uselib(struct nameidata *nd)
+{
+	return security_ops->path_uselib(nd);
+}
+
 int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
 {
 	if (unlikely(IS_PRIVATE(dir)))

--

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ