update patches to 2.6.26

This commit is contained in:
John Johansen 2008-07-02 20:24:33 +00:00
parent 748e398c21
commit 6a3e6c68be
122 changed files with 1744 additions and 16749 deletions

View file

@ -1,144 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: Fix __d_path to allow for old and new behavior bnc#380763
Fix __d_path so that it can be told whether or not to connect
disconnect path to the root. This is easier and more efficient
than trying to reconnect these paths for d_path and get_cwd
after the fact.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 57 ++++++++++++++++++-------------------------------
fs/namespace.c | 2 -
include/linux/dcache.h | 2 -
3 files changed, 24 insertions(+), 37 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1772,6 +1772,7 @@ shouldnt_be_hashed:
* @buffer: buffer to return value in
* @buflen: buffer length
* @fail_deleted: what to return for deleted files
+ * @disconnect: don't return a path starting with / when disconnected
*
* Convert a dentry into an ASCII path name. If the entry has been deleted,
* then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
@@ -1784,9 +1785,10 @@ shouldnt_be_hashed:
*/
char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
struct dentry *root, struct vfsmount *rootmnt,
- char *buffer, int buflen, int fail_deleted)
+ char *buffer, int buflen, int fail_deleted, int disconnect)
{
- int namelen, is_slash, vfsmount_locked = 0;
+ int namelen, vfsmount_locked = 0;
+ const unsigned char *name;
if (buflen < 2)
return ERR_PTR(-ENAMETOOLONG);
@@ -1847,27 +1849,26 @@ global_root:
* unconnected dentry, or the file is on a pseudo filesystem.
*/
namelen = dentry->d_name.len;
- is_slash = (namelen == 1 && *dentry->d_name.name == '/');
- if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
- /*
- * Make sure we won't return a pathname starting with '/'.
- *
- * Historically, we also glue together the root dentry and
- * remaining name for pseudo filesystems like pipefs, which
- * have the MS_NOUSER flag set. This results in pathnames
- * like "pipe:[439336]".
- */
- if (*buffer == '/') {
- buffer++;
- buflen++;
- }
- if (is_slash)
- goto out;
+ name = dentry->d_name.name;
+
+ /*
+ * If this is a root dentry, then overwrite the slash. This
+ * will also DTRT with pseudo filesystems which have root
+ * dentries named "foo:".
+ */
+ if (IS_ROOT(dentry)) {
+ buffer++;
+ buflen++;
+ }
+ if (disconnect && *name == '/') {
+ /* Make sure we won't return a pathname starting with '/' */
+ name++;
+ namelen--;
}
if (buflen < namelen)
goto Elong;
buffer -= namelen;
- memcpy(buffer, dentry->d_name.name, namelen);
+ memcpy(buffer, name, namelen);
goto out;
Elong:
@@ -1875,18 +1876,6 @@ Elong:
goto out;
}
-static char *__connect_d_path(char *path, char *buffer)
-{
- if (!IS_ERR(path) && *path != '/') {
- /* Pretend that disconnected paths are hanging off the root. */
- if (path == buffer)
- path = ERR_PTR(-ENAMETOOLONG);
- else
- *--path = '/';
- }
- return path;
-}
-
/* write full pathname into buffer and return start of pathname */
char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
int buflen)
@@ -1909,8 +1898,7 @@ char *d_path(struct dentry *dentry, stru
rootmnt = mntget(current->fs->rootmnt);
root = dget(current->fs->root);
read_unlock(&current->fs->lock);
- res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
- res = __connect_d_path(res, buf);
+ res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0, 0);
dput(root);
mntput(rootmnt);
return res;
@@ -1972,8 +1960,7 @@ asmlinkage long sys_getcwd(char __user *
root = dget(current->fs->root);
read_unlock(&current->fs->lock);
- cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
- cwd = __connect_d_path(cwd, page);
+ cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1, 0);
error = PTR_ERR(cwd);
if (IS_ERR(cwd))
goto out;
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1901,7 +1901,7 @@ char *d_namespace_path(struct dentry *de
mntput(rootmnt);
if (nsrootmnt)
root = dget(nsrootmnt->mnt_root);
- res = __d_path(dentry, vfsmnt, root, nsrootmnt, buf, buflen, 1);
+ res = __d_path(dentry, vfsmnt, root, nsrootmnt, buf, buflen, 1, 1);
dput(root);
mntput(nsrootmnt);
/* Prevent empty path for lazily unmounted filesystems. */
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -301,7 +301,7 @@ extern int d_validate(struct dentry *, s
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
extern char *__d_path(struct dentry *, struct vfsmount *, struct dentry *,
- struct vfsmount *, char *, int, int);
+ struct vfsmount *, char *, int, int, int);
extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
/* Allocation counts.. */

View file

@ -0,0 +1,60 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: Patch AppArmor for 2.6.25 kernel
Add 64 bit capabilities support to AppArmor.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
security/apparmor/lsm.c | 3 ++-
security/apparmor/module_interface.c | 22 ++++++++++++++++++----
2 files changed, 20 insertions(+), 5 deletions(-)
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -462,7 +462,8 @@ static int apparmor_inode_permission(str
/* allow traverse accesses to directories */
mask &= ~MAY_EXEC;
}
- return aa_permission("inode_permission", inode, nd->dentry, nd->mnt,
+ return aa_permission("inode_permission", inode, nd->path.dentry,
+ nd->path.mnt,
mask, check);
}
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -394,15 +394,29 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
goto fail;
- if (!aa_is_u32(e, &(profile->capabilities), NULL))
+ if (!aa_is_u32(e, &(profile->capabilities.cap[0]), NULL))
goto fail;
- if (!aa_is_u32(e, &(profile->audit_caps), NULL))
+ if (!aa_is_u32(e, &(profile->audit_caps.cap[0]), NULL))
goto fail;
- if (!aa_is_u32(e, &(profile->quiet_caps), NULL))
+ if (!aa_is_u32(e, &(profile->quiet_caps.cap[0]), NULL))
goto fail;
- if (!aa_is_u32(e, &(profile->set_caps), NULL))
+ if (!aa_is_u32(e, &(profile->set_caps.cap[0]), NULL))
goto fail;
+ if (aa_is_nameX(e, AA_STRUCT, "caps64")) {
+ /* optional upper half of 64 bit caps */
+ if (!aa_is_u32(e, &(profile->capabilities.cap[1]), NULL))
+ goto fail;
+ if (!aa_is_u32(e, &(profile->audit_caps.cap[1]), NULL))
+ goto fail;
+ if (!aa_is_u32(e, &(profile->quiet_caps.cap[1]), NULL))
+ goto fail;
+ if (!aa_is_u32(e, &(profile->set_caps.cap[1]), NULL))
+ goto fail;
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+ goto fail;
+ }
+
if (!aa_unpack_rlimits(e, profile))
goto fail;

View file

@ -1,745 +0,0 @@
---
security/apparmor/apparmor.h | 14 -
security/apparmor/apparmorfs.c | 2
security/apparmor/inline.h | 14 -
security/apparmor/main.c | 490 +++++++++++++++++++----------------
security/apparmor/match.c | 9
security/apparmor/module_interface.c | 10
6 files changed, 309 insertions(+), 230 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -44,8 +44,7 @@
AA_EXEC_MOD_2 | AA_EXEC_MOD_3 | \
AA_EXEC_MOD_4)
-#define AA_EXEC_TYPE (MAY_EXEC | AA_EXEC_UNSAFE | \
- AA_EXEC_MODIFIERS)
+#define AA_EXEC_TYPE (AA_EXEC_UNSAFE | AA_EXEC_MODIFIERS)
#define AA_EXEC_UNCONFINED AA_EXEC_MOD_0
#define AA_EXEC_INHERIT AA_EXEC_MOD_1
@@ -85,6 +84,10 @@
AA_AUDIT_FIELD)
#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_SHARED_PERMS)
+
+/* audit bits for the second accept field */
+#define AUDIT_FILE_MASK 0x1fc07f
+#define AUDIT_QUIET_MASK(mask) ((mask >> 7) & AUDIT_FILE_MASK)
#define AA_VALID_PERM2_MASK 0x0fffffff
#define AA_SECURE_EXEC_NEEDED 1
@@ -179,6 +182,9 @@ struct aa_profile {
int isstale;
kernel_cap_t capabilities;
+ kernel_cap_t audit_caps;
+ kernel_cap_t quiet_caps;
+
struct kref count;
struct list_head task_contexts;
spinlock_t lock;
@@ -226,7 +232,7 @@ struct aa_audit {
const char *name;
const char *name2;
const char *name3;
- int request_mask, denied_mask;
+ int request_mask, denied_mask, audit_mask;
struct iattr *iattr;
pid_t task, parent;
int error_code;
@@ -331,7 +337,7 @@ extern struct aa_dfa *aa_match_alloc(voi
extern void aa_match_free(struct aa_dfa *dfa);
extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
extern int verify_dfa(struct aa_dfa *dfa);
-extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str);
+extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *);
extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
const char *str);
extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -89,7 +89,7 @@ static struct file_operations apparmorfs
static ssize_t aa_matching_read(struct file *file, char __user *buf,
size_t size, loff_t *ppos)
{
- const char *matching = "pattern=aadfa perms=rwxamlk/ user::other";
+ const char *matching = "pattern=aadfa audit perms=rwxamlk/ user::other";
return simple_read_from_buffer(buf, size, ppos, matching,
strlen(matching));
--- a/security/apparmor/inline.h
+++ b/security/apparmor/inline.h
@@ -232,9 +232,19 @@ static inline void unlock_both_profiles(
}
}
-static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname)
+static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname,
+ int *audit_mask)
{
- return dfa ? aa_dfa_match(dfa, pathname) : 0;
+ if (dfa)
+ return aa_dfa_match(dfa, pathname, audit_mask);
+ if (audit_mask)
+ *audit_mask = 0;
+ return 0;
+}
+
+static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state)
+{
+ return ACCEPT_TABLE2(dfa)[state];
}
#endif /* __INLINE_H__ */
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -36,204 +36,6 @@ static int aa_inode_mode(struct inode *i
return AA_OTHER_SHIFT;
}
-/**
- * aa_file_denied - check for @mask access on a file
- * @profile: profile to check against
- * @name: pathname of file
- * @mask: permission mask requested for file
- *
- * Return %0 on success, or else the permissions in @mask that the
- * profile denies.
- */
-static int aa_file_denied(struct aa_profile *profile, const char *name,
- int mask)
-{
- return (mask & ~aa_match(profile->file_rules, name));
-}
-
-/**
- * aa_link_denied - check for permission to link a file
- * @profile: profile to check against
- * @link: pathname of link being created
- * @target: pathname of target to be linked to
- * @target_mode: UGO shift for target inode
- * @request_mask: the permissions subset valid only if link succeeds
- * Return %0 on success, or else the permissions that the profile denies.
- */
-static int aa_link_denied(struct aa_profile *profile, const char *link,
- const char *target, int target_mode,
- int *request_mask)
-{
- unsigned int state;
- int l_mode, t_mode, denied_mask = 0;
- int link_mask = AA_MAY_LINK << target_mode;
-
- *request_mask = link_mask;
-
- l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state);
- if (l_mode & link_mask) {
- int mode;
- /* test to see if target can be paired with link */
- state = aa_dfa_null_transition(profile->file_rules, state);
- mode = aa_match_state(profile->file_rules, state, target,
- NULL);
-
- if (!(mode & link_mask))
- denied_mask |= link_mask;
- /* return if link subset test is not required */
- if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
- return denied_mask;
- }
-
- /* Do link perm subset test
- * If a subset test is required a permission subset test of the
- * perms for the link are done against the user::other of the
- * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
- *
- * If the link has 'x', an exact match of all the execute flags
- * must match.
- */
- denied_mask |= ~l_mode & link_mask;
-
- t_mode = aa_match(profile->file_rules, target);
-
- /* For actual subset test ignore valid-profile-transition flags,
- * and link bits
- */
- l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
- t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
-
- *request_mask = l_mode | link_mask;
-
- if (l_mode) {
- denied_mask |= l_mode & ~t_mode;
- if ((l_mode & AA_EXEC_BITS) &&
- (l_mode & ALL_AA_EXEC_TYPE) !=
- (t_mode & ALL_AA_EXEC_TYPE))
- denied_mask = (denied_mask & ~ALL_AA_EXEC_TYPE) |
- (l_mode & ALL_AA_EXEC_TYPE);
- }
-
- return denied_mask;
-}
-
-/**
- * aa_get_name - compute the pathname of a file
- * @dentry: dentry of the file
- * @mnt: vfsmount of the file
- * @buffer: buffer that aa_get_name() allocated
- * @check: AA_CHECK_DIR is set if the file is a directory
- *
- * Returns a pointer to the beginning of the pathname (which usually differs
- * from the beginning of the buffer), or an error code.
- *
- * We need @check to indicate whether the file is a directory or not because
- * the file may not yet exist, and so we cannot check the inode's file type.
- */
-static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
- char **buffer, int check)
-{
- char *name;
- int is_dir, size = 256;
-
- is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
-
- for (;;) {
- char *buf = kmalloc(size, GFP_KERNEL);
- if (!buf)
- return ERR_PTR(-ENOMEM);
-
- name = d_namespace_path(dentry, mnt, buf, size - is_dir);
- if (!IS_ERR(name)) {
- if (name[0] != '/') {
- /*
- * This dentry is not connected to the
- * namespace root -- reject access.
- */
- kfree(buf);
- return ERR_PTR(-ENOENT);
- }
- if (is_dir && name[1] != '\0') {
- /*
- * Append "/" to the pathname. The root
- * directory is a special case; it already
- * ends in slash.
- */
- buf[size - 2] = '/';
- buf[size - 1] = '\0';
- }
-
- *buffer = buf;
- return name;
- }
- if (PTR_ERR(name) != -ENAMETOOLONG)
- return name;
-
- kfree(buf);
- size <<= 1;
- if (size > apparmor_path_max)
- return ERR_PTR(-ENAMETOOLONG);
- }
-}
-
-static inline void aa_put_name_buffer(char *buffer)
-{
- kfree(buffer);
-}
-
-/**
- * aa_perm_dentry - check if @profile allows @mask for a file
- * @profile: profile to check against
- * @dentry: dentry of the file
- * @mnt: vfsmount o the file
- * @sa: audit context
- * @mask: requested profile permissions
- * @check: kind of check to perform
- *
- * Returns 0 upon success, or else an error code.
- *
- * @check indicates the file type, and whether the file was accessed through
- * an open file descriptor (AA_CHECK_FD) or not.
- */
-static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
- struct vfsmount *mnt, struct aa_audit *sa, int check)
-{
- int error;
- char *buffer = NULL;
-
- sa->name = aa_get_name(dentry, mnt, &buffer, check);
- sa->request_mask <<= aa_inode_mode(dentry->d_inode);
- if (IS_ERR(sa->name)) {
- /*
- * deleted files are given a pass on permission checks when
- * accessed through a file descriptor.
- */
- if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
- sa->denied_mask = 0;
- else {
- sa->denied_mask = sa->request_mask;
- sa->error_code = PTR_ERR(sa->name);
- if (sa->error_code == -ENOENT)
- sa->info = "Failed name resolution - object not a valid entry";
- else if (sa->error_code == -ENAMETOOLONG)
- sa->info = "Failed name resolution - name too long";
- else
- sa->info = "Failed name resolution";
- }
- sa->name = NULL;
- } else
- sa->denied_mask = aa_file_denied(profile, sa->name,
- sa->request_mask);
-
- if (!sa->denied_mask)
- sa->error_code = 0;
-
- error = aa_audit(profile, sa);
- aa_put_name_buffer(buffer);
-
- return error;
-}
-
int alloc_default_namespace(void)
{
struct aa_namespace *ns;
@@ -471,20 +273,259 @@ int aa_audit(struct aa_profile *profile,
int type = AUDIT_APPARMOR_DENIED;
struct audit_context *audit_cxt;
- if (likely(!sa->error_code)) {
- if (likely(!PROFILE_AUDIT(profile)))
- /* nothing to log */
- return 0;
- else
- type = AUDIT_APPARMOR_AUDIT;
- } else if (PROFILE_COMPLAIN(profile)) {
+ if (likely(!sa->error_code))
+ type = AUDIT_APPARMOR_AUDIT;
+ else if (PROFILE_COMPLAIN(profile))
type = AUDIT_APPARMOR_ALLOWED;
- }
audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
return aa_audit_base(profile, sa, audit_cxt, type);
}
+static int aa_audit_file(struct aa_profile *profile, struct aa_audit *sa)
+{
+ if (likely(!sa->error_code)) {
+ int mask = sa->audit_mask & AUDIT_FILE_MASK;
+
+ if (unlikely(PROFILE_AUDIT(profile)))
+ mask |= AUDIT_FILE_MASK;
+
+ if (likely(!(sa->request_mask & mask)))
+ return 0;
+
+ /* mask off perms that are not being force audited */
+ sa->request_mask &= mask | ALL_AA_EXEC_TYPE;
+ } else {
+ int mask = AUDIT_QUIET_MASK(sa->audit_mask);
+
+ if (!(sa->denied_mask & ~mask))
+ return sa->error_code;
+
+ /* mask off perms whose denial is being silenced */
+ sa->denied_mask &= (~mask) | ALL_AA_EXEC_TYPE;
+ }
+
+ return aa_audit(profile, sa);
+}
+
+static int aa_audit_caps(struct aa_profile *profile, struct aa_audit *sa,
+ int cap)
+{
+ if (likely(!sa->error_code)) {
+ if (likely(!PROFILE_AUDIT(profile) &&
+ !cap_raised(profile->audit_caps, cap)))
+ return 0;
+ }
+
+ /* quieting of capabilities is handled the caps_logged cache */
+ return aa_audit(profile, sa);
+}
+
+/**
+ * aa_file_denied - check for @mask access on a file
+ * @profile: profile to check against
+ * @name: pathname of file
+ * @mask: permission mask requested for file
+ * @audit_mask: return audit mask for the match
+ *
+ * Return %0 on success, or else the permissions in @mask that the
+ * profile denies.
+ */
+static int aa_file_denied(struct aa_profile *profile, const char *name,
+ int mask, int *audit_mask)
+{
+ return (mask & ~aa_match(profile->file_rules, name, audit_mask));
+}
+
+/**
+ * aa_link_denied - check for permission to link a file
+ * @profile: profile to check against
+ * @link: pathname of link being created
+ * @target: pathname of target to be linked to
+ * @target_mode: UGO shift for target inode
+ * @request_mask: the permissions subset valid only if link succeeds
+ * @audit_mask: return the audit_mask for the link permission
+ * Return %0 on success, or else the permissions that the profile denies.
+ */
+static int aa_link_denied(struct aa_profile *profile, const char *link,
+ const char *target, int target_mode,
+ int *request_mask, int *audit_mask)
+{
+ unsigned int state;
+ int l_mode, t_mode, denied_mask = 0;
+ int link_mask = AA_MAY_LINK << target_mode;
+
+ *request_mask = link_mask;
+
+ l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state);
+
+ if (l_mode & link_mask) {
+ int mode;
+ /* test to see if target can be paired with link */
+ state = aa_dfa_null_transition(profile->file_rules, state);
+ mode = aa_match_state(profile->file_rules, state, target,
+ &state);
+
+ if (!(mode & link_mask))
+ denied_mask |= link_mask;
+
+ *audit_mask = dfa_audit_mask(profile->file_rules, state);
+
+ /* return if link subset test is not required */
+ if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
+ return denied_mask;
+ }
+
+ /* Do link perm subset test
+ * If a subset test is required a permission subset test of the
+ * perms for the link are done against the user::other of the
+ * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
+ *
+ * If the link has 'x', an exact match of all the execute flags
+ * must match.
+ */
+ denied_mask |= ~l_mode & link_mask;
+
+ t_mode = aa_match(profile->file_rules, target, NULL);
+
+ /* For actual subset test ignore valid-profile-transition flags,
+ * and link bits
+ */
+ l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
+ t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
+
+ *request_mask = l_mode | link_mask;
+
+ if (l_mode) {
+ denied_mask |= l_mode & ~t_mode;
+ if ((l_mode & AA_EXEC_BITS) &&
+ (l_mode & ALL_AA_EXEC_TYPE) !=
+ (t_mode & ALL_AA_EXEC_TYPE))
+ denied_mask = (denied_mask & ~ALL_AA_EXEC_TYPE) |
+ (l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS));
+ }
+
+ return denied_mask;
+}
+
+/**
+ * aa_get_name - compute the pathname of a file
+ * @dentry: dentry of the file
+ * @mnt: vfsmount of the file
+ * @buffer: buffer that aa_get_name() allocated
+ * @check: AA_CHECK_DIR is set if the file is a directory
+ *
+ * Returns a pointer to the beginning of the pathname (which usually differs
+ * from the beginning of the buffer), or an error code.
+ *
+ * We need @check to indicate whether the file is a directory or not because
+ * the file may not yet exist, and so we cannot check the inode's file type.
+ */
+static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
+ char **buffer, int check)
+{
+ char *name;
+ int is_dir, size = 256;
+
+ is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
+
+ for (;;) {
+ char *buf = kmalloc(size, GFP_KERNEL);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+ name = d_namespace_path(dentry, mnt, buf, size - is_dir);
+ if (!IS_ERR(name)) {
+ if (name[0] != '/') {
+ /*
+ * This dentry is not connected to the
+ * namespace root -- reject access.
+ */
+ kfree(buf);
+ return ERR_PTR(-ENOENT);
+ }
+ if (is_dir && name[1] != '\0') {
+ /*
+ * Append "/" to the pathname. The root
+ * directory is a special case; it already
+ * ends in slash.
+ */
+ buf[size - 2] = '/';
+ buf[size - 1] = '\0';
+ }
+
+ *buffer = buf;
+ return name;
+ }
+ if (PTR_ERR(name) != -ENAMETOOLONG)
+ return name;
+
+ kfree(buf);
+ size <<= 1;
+ if (size > apparmor_path_max)
+ return ERR_PTR(-ENAMETOOLONG);
+ }
+}
+
+static inline void aa_put_name_buffer(char *buffer)
+{
+ kfree(buffer);
+}
+
+/**
+ * aa_perm_dentry - check if @profile allows @mask for a file
+ * @profile: profile to check against
+ * @dentry: dentry of the file
+ * @mnt: vfsmount o the file
+ * @sa: audit context
+ * @mask: requested profile permissions
+ * @check: kind of check to perform
+ *
+ * Returns 0 upon success, or else an error code.
+ *
+ * @check indicates the file type, and whether the file was accessed through
+ * an open file descriptor (AA_CHECK_FD) or not.
+ */
+static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
+ struct vfsmount *mnt, struct aa_audit *sa, int check)
+{
+ int error;
+ char *buffer = NULL;
+
+ sa->name = aa_get_name(dentry, mnt, &buffer, check);
+ sa->request_mask <<= aa_inode_mode(dentry->d_inode);
+ if (IS_ERR(sa->name)) {
+ /*
+ * deleted files are given a pass on permission checks when
+ * accessed through a file descriptor.
+ */
+ if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
+ sa->denied_mask = 0;
+ else {
+ sa->denied_mask = sa->request_mask;
+ sa->error_code = PTR_ERR(sa->name);
+ if (sa->error_code == -ENOENT)
+ sa->info = "Failed name resolution - object not a valid entry";
+ else if (sa->error_code == -ENAMETOOLONG)
+ sa->info = "Failed name resolution - name too long";
+ else
+ sa->info = "Failed name resolution";
+ }
+ sa->name = NULL;
+ } else
+ sa->denied_mask = aa_file_denied(profile, sa->name,
+ sa->request_mask,
+ &sa->audit_mask);
+
+ if (!sa->denied_mask)
+ sa->error_code = 0;
+
+ error = aa_audit_file(profile, sa);
+ aa_put_name_buffer(buffer);
+
+ return error;
+}
+
/**
* aa_attr - check if attribute change is allowed
* @profile: profile to check against
@@ -621,10 +662,11 @@ int aa_perm_path(struct aa_profile *prof
else
sa.request_mask = mask << AA_OTHER_SHIFT;
- sa.denied_mask = aa_file_denied(profile, name, sa.request_mask) ;
+ sa.denied_mask = aa_file_denied(profile, name, sa.request_mask,
+ &sa.audit_mask) ;
sa.error_code = sa.denied_mask ? -EACCES : 0;
- return aa_audit(profile, &sa);
+ return aa_audit_file(profile, &sa);
}
/**
@@ -660,7 +702,7 @@ int aa_capability(struct aa_task_context
sa.name = capability_names[cap];
sa.error_code = error;
- error = aa_audit(cxt->profile, &sa);
+ error = aa_audit_caps(cxt->profile, &sa, cap);
return error;
}
@@ -709,11 +751,12 @@ int aa_link(struct aa_profile *profile,
if (sa.name && sa.name2) {
sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2,
aa_inode_mode(target->d_inode),
- &sa.request_mask);
+ &sa.request_mask,
+ &sa.audit_mask);
sa.error_code = sa.denied_mask ? -EACCES : 0;
}
- error = aa_audit(profile, &sa);
+ error = aa_audit_file(profile, &sa);
aa_put_name_buffer(buffer);
aa_put_name_buffer(buffer2);
@@ -802,8 +845,8 @@ aa_register_find(struct aa_profile *prof
new_profile =
aa_dup_profile(profile->ns->null_complain_profile);
} else {
- aa_audit_reject(profile, sa);
- return ERR_PTR(-EACCES); /* was -EPERM */
+ sa->error_code = -EACCES;
+ return ERR_PTR(aa_audit_file(profile, sa));
}
} else {
/* Only way we can get into this code is if task
@@ -863,7 +906,8 @@ repeat:
/* Confined task, determine what mode inherit, unconfined or
* mandatory to load new profile
*/
- exec_mode = aa_match(profile->file_rules, filename);
+ exec_mode = aa_match(profile->file_rules, filename,
+ &sa.audit_mask);
if (exec_mode & sa.request_mask) {
switch ((exec_mode >> shift) & AA_EXEC_MODIFIERS) {
@@ -906,6 +950,9 @@ repeat:
break;
}
+ } else if (sa.request_mask & AUDIT_QUIET_MASK(sa.audit_mask)) {
+ /* quiet failed exit */
+ new_profile = ERR_PTR(-EACCES);
} else if (complain) {
/* There was no entry in calling profile
* describing mode to execute image in.
@@ -916,8 +963,8 @@ repeat:
exec_mode |= AA_EXEC_UNSAFE << shift;
} else {
sa.denied_mask = sa.request_mask;
- aa_audit_reject(profile, &sa);
- new_profile = ERR_PTR(-EPERM);
+ sa.error_code = -EACCES;
+ new_profile = ERR_PTR(aa_audit_file(profile, &sa));
}
} else {
/* Unconfined task, load profile if it exists */
@@ -973,6 +1020,7 @@ repeat:
sa.info = "set profile";
aa_audit_hint(new_profile, &sa);
}
+
cleanup:
aa_put_name_buffer(buffer);
if (IS_ERR(new_profile))
@@ -1149,7 +1197,7 @@ repeat:
if (PROFILE_COMPLAIN(profile) ||
(ns == profile->ns &&
- (aa_match(profile->file_rules, name) & AA_CHANGE_PROFILE)))
+ (aa_match(profile->file_rules, name, NULL) & AA_CHANGE_PROFILE)))
error = do_change_profile(profile, ns, name, 0, 0, &sa);
else {
/* check for a rule with a namespace prepended */
@@ -1356,9 +1404,11 @@ void aa_change_task_context(struct task_
call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
}
if (new_cxt) {
- /* clear the caps_logged cache, so that new profile/hat has
- * chance to emit its own set of cap messages */
- new_cxt->caps_logged = CAP_EMPTY_SET;
+ /* set the caps_logged cache to the quiet_caps mask
+ * this has the effect of quieting caps that are not
+ * supposed to be logged
+ */
+ new_cxt->caps_logged = profile->quiet_caps;
new_cxt->cookie = cookie;
new_cxt->task = task;
new_cxt->profile = aa_dup_profile(profile);
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -14,6 +14,7 @@
#include <linux/errno.h>
#include "apparmor.h"
#include "match.h"
+#include "inline.h"
static struct table_header *unpack_table(void *blob, size_t bsize)
{
@@ -295,13 +296,17 @@ unsigned int aa_dfa_null_transition(stru
* aa_dfa_match - find accept perm for @str in @dfa
* @dfa: the dfa to match @str against
* @str: the string to match against the dfa
+ * @audit_mask: the audit_mask for the final state
*
* aa_dfa_match will match @str and return the accept perms for the
* final state.
*/
-unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str)
+unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *audit_mask)
{
- return ACCEPT_TABLE(dfa)[aa_dfa_next_state(dfa, DFA_START, str)];
+ int state = aa_dfa_next_state(dfa, DFA_START, str);
+ if (audit_mask)
+ *audit_mask = dfa_audit_mask(dfa, state);
+ return ACCEPT_TABLE(dfa)[state];
}
/**
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -310,6 +310,10 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_u32(e, &(profile->capabilities), NULL))
goto fail;
+ if (!aa_is_u32(e, &(profile->audit_caps), NULL))
+ goto fail;
+ if (!aa_is_u32(e, &(profile->quiet_caps), NULL))
+ goto fail;
/* get file rules */
profile->file_rules = aa_unpack_dfa(e);
@@ -317,6 +321,10 @@ static struct aa_profile *aa_unpack_prof
error = PTR_ERR(profile->file_rules);
profile->file_rules = NULL;
goto fail;
+ if (!aa_is_u16(e, &profile->audit_network[i], NULL))
+ goto fail;
+ if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
+ goto fail;
}
if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
@@ -360,7 +368,7 @@ static int aa_verify_header(struct aa_ex
}
/* check that the interface version is currently supported */
- if (e->version != 3) {
+ if (e->version != 4) {
struct aa_audit sa;
memset(&sa, 0, sizeof(sa));
sa.operation = operation;

View file

@ -27,9 +27,9 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* 1600 - 1699 kernel crypto events
* 1700 - 1799 kernel anomaly records
* 1800 - 1999 future kernel use (maybe integrity labels and related events)
@@ -116,6 +116,13 @@
#define AUDIT_MAC_IPSEC_DELSPD 1414 /* Not used */
#define AUDIT_MAC_IPSEC_EVENT 1415 /* Audit an IPSec event */
@@ -119,6 +119,13 @@
#define AUDIT_MAC_UNLBL_STCADD 1416 /* NetLabel: add a static label */
#define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */
+#define AUDIT_APPARMOR_AUDIT 1501 /* AppArmor audited grants */
+#define AUDIT_APPARMOR_ALLOWED 1502 /* Allowed Access for learning */
@ -41,7 +41,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
#define AUDIT_LAST_KERN_ANOM_MSG 1799
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
@@ -513,6 +520,9 @@ extern void audit_log(struct audit_
@@ -546,6 +553,9 @@ extern void audit_log(struct audit_
__attribute__((format(printf,4,5)));
extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
@ -53,7 +53,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
__attribute__((format(printf,2,3)));
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1215,8 +1215,7 @@ static inline int audit_expand(struct au
@@ -1226,8 +1226,7 @@ static inline int audit_expand(struct au
* will be called a second time. Currently, we assume that a printk
* can't format message larger than 1024 bytes, so we don't either.
*/
@ -63,7 +63,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
{
int len, avail;
struct sk_buff *skb;
@@ -1471,3 +1470,6 @@ EXPORT_SYMBOL(audit_log_start);
@@ -1501,3 +1500,6 @@ EXPORT_SYMBOL(audit_log_start);
EXPORT_SYMBOL(audit_log_end);
EXPORT_SYMBOL(audit_log_format);
EXPORT_SYMBOL(audit_log);

View file

@ -1,61 +0,0 @@
---
security/apparmor/Kconfig | 17 +++++++++++++++++
security/apparmor/lsm.c | 16 ++++++++++++++++
2 files changed, 33 insertions(+)
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -7,4 +7,21 @@ config SECURITY_APPARMOR
Required userspace tools (if they are not included in your
distribution) and further information may be found at
<http://forge.novell.com/modules/xfmod/project/?apparmor>
+
If you are unsure how to answer this question, answer N.
+
+config SECURITY_APPARMOR_BOOTPARAM_VALUE
+ int "AppArmor boot parameter default value"
+ depends on SECURITY_APPARMOR
+ range 0 1
+ default 1
+ help
+ This option sets the default value for the kernel parameter
+ 'apparmor', which allows AppArmor to be enabled or disabled
+ at boot. If this option is set to 0 (zero), the AppArmor
+ kernel parameter will default to 0, disabling AppArmor at
+ bootup. If this option is set to 1 (one), the AppArmor
+ kernel parameter will default to 1, enabling AppArmor at
+ bootup.
+
+ If you are unsure how to answer this question, answer 1.
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -23,6 +23,17 @@
#include "apparmor.h"
#include "inline.h"
+/* Boot time disable flag */
+int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
+
+static int __init apparmor_enabled_setup(char *str)
+{
+ apparmor_enabled = simple_strtol(str, NULL, 0);
+ return 1;
+}
+__setup("apparmor=", apparmor_enabled_setup);
+
+
static int param_set_aabool(const char *val, struct kernel_param *kp);
static int param_get_aabool(char *buffer, struct kernel_param *kp);
#define param_check_aabool(name, p) __param_check(name, p, int)
@@ -882,6 +893,11 @@ static int __init apparmor_init(void)
{
int error;
+ if (!apparmor_enabled) {
+ info_message("AppArmor disabled by boottime parameter\n");
+ return 0;
+ }
+
if ((error = create_apparmorfs())) {
AA_ERROR("Unable to activate AppArmor filesystem\n");
goto createfs_out;

View file

@ -1,50 +0,0 @@
---
security/apparmor/Kconfig | 2 +-
security/apparmor/lsm.c | 26 --------------------------
2 files changed, 1 insertion(+), 27 deletions(-)
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -1,5 +1,5 @@
config SECURITY_APPARMOR
- tristate "AppArmor support"
+ bool "AppArmor support"
depends on SECURITY
select AUDIT
help
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -931,33 +931,7 @@ createfs_out:
}
-static void __exit apparmor_exit(void)
-{
- /* Remove and release all the profiles on the profile list. */
- mutex_lock(&aa_interface_lock);
- aa_profile_ns_list_release();
-
- /* FIXME: cleanup profiles references on files */
- free_default_namespace();
-
- /*
- * Delay for an rcu cycle to make sure that all active task
- * context readers have finished, and all profiles have been
- * freed by their rcu callbacks.
- */
- synchronize_rcu();
-
- destroy_apparmorfs();
- mutex_unlock(&aa_interface_lock);
-
- if (unregister_security(&apparmor_ops))
- info_message("Unable to properly unregister AppArmor");
-
- info_message("AppArmor protection removed");
-}
-
module_init(apparmor_init);
-module_exit(apparmor_exit);
MODULE_DESCRIPTION("AppArmor process confinement");
MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");

View file

@ -1,16 +0,0 @@
---
security/apparmor/lsm.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -366,8 +366,7 @@ static inline int aa_mask_permissions(in
static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mask)
{
- /* FIXME: may move to MAY_APPEND later */
- return aa_permission("inode_create", dir, dentry, mnt, MAY_WRITE, 0);
+ return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
}
static int apparmor_inode_link(struct dentry *old_dentry,

View file

@ -1,83 +0,0 @@
---
security/apparmor/main.c | 39 ++++++++++++++++++++++++++++-----------
1 file changed, 28 insertions(+), 11 deletions(-)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -216,6 +216,12 @@ static int aa_perm_dentry(struct aa_prof
else {
sa->denied_mask = sa->request_mask;
sa->error_code = PTR_ERR(sa->name);
+ if (sa->error_code == -ENOENT)
+ sa->info = "Failed name resolution - object not a valid entry";
+ else if (sa->error_code == -ENAMETOOLONG)
+ sa->info = "Failed name resolution - name too long";
+ else
+ sa->info = "Failed name resolution";
}
sa->name = NULL;
} else
@@ -371,8 +377,11 @@ static int aa_audit_base(struct aa_profi
if (sa->operation)
audit_log_format(ab, "operation=\"%s\"", sa->operation);
- if (sa->info)
+ if (sa->info) {
audit_log_format(ab, " info=\"%s\"", sa->info);
+ if (sa->error_code)
+ audit_log_format(ab, " error=%d", sa->error_code);
+ }
if (sa->request_mask)
aa_audit_file_mask(ab, "requested_mask", sa->request_mask);
@@ -918,23 +927,29 @@ int aa_register(struct linux_binprm *bpr
AA_DEBUG("%s\n", __FUNCTION__);
- filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer, 0);
- if (IS_ERR(filename)) {
- AA_ERROR("%s: Failed to get filename", __FUNCTION__);
- return -ENOENT;
- }
+ profile = aa_get_profile(current);
shift = aa_inode_mode(filp->f_dentry->d_inode);
- exec_mode = AA_EXEC_UNSAFE << shift;
-
memset(&sa, 0, sizeof(sa));
sa.operation = "exec";
sa.gfp_mask = GFP_KERNEL;
- sa.name = filename;
sa.request_mask = MAY_EXEC << shift;
+ filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer, 0);
+ if (IS_ERR(filename)) {
+ if (profile) {
+ sa.info = "Failed name resolution - exec failed";
+ sa.error_code = PTR_ERR(filename);
+ aa_audit_reject(profile, &sa);
+ return sa.error_code;
+ } else
+ return 0;
+ }
+ sa.name = filename;
+
+ exec_mode = AA_EXEC_UNSAFE << shift;
+
repeat:
- profile = aa_get_profile(current);
if (profile) {
complain = PROFILE_COMPLAIN(profile);
@@ -1011,8 +1026,10 @@ repeat:
if (IS_ERR(old_profile)) {
aa_put_profile(new_profile);
aa_put_profile(profile);
- if (PTR_ERR(old_profile) == -ESTALE)
+ if (PTR_ERR(old_profile) == -ESTALE) {
+ profile = aa_get_profile(current);
goto repeat;
+ }
if (PTR_ERR(old_profile) == -EPERM) {
sa.denied_mask = sa.request_mask;
sa.info = "unable to set profile due to ptrace";

View file

@ -1,47 +0,0 @@
---
security/apparmor/apparmorfs.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -99,6 +99,22 @@ static struct file_operations apparmorfs
.read = aa_matching_read,
};
+/* apparmor/features */
+static ssize_t aa_features_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char *features = "file=3.0 capability=1.0 network=1.0 "
+ "change_hat=1.3 change_profile=1.0 "
+ "aanamespaces=1.0";
+
+ return simple_read_from_buffer(buf, size, ppos, features,
+ strlen(features));
+}
+
+static struct file_operations apparmorfs_features_fops = {
+ .read = aa_features_read,
+};
+
/* apparmor/.load */
static ssize_t aa_profile_load(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
@@ -204,6 +220,7 @@ void destroy_apparmorfs(void)
aafs_remove(".replace");
aafs_remove(".load");
aafs_remove("matching");
+ aafs_remove("features");
aafs_remove("profiles");
securityfs_remove(apparmor_dentry);
apparmor_dentry = NULL;
@@ -232,6 +249,9 @@ int create_apparmorfs(void)
error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
if (error)
goto error;
+ error = aafs_create("features", 0444, &apparmorfs_features_fops);
+ if (error)
+ goto error;
error = aafs_create(".load", 0640, &apparmorfs_profile_load);
if (error)
goto error;

View file

@ -1,36 +0,0 @@
---
security/apparmor/apparmorfs.c | 2 +-
security/apparmor/main.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -89,7 +89,7 @@ static struct file_operations apparmorfs
static ssize_t aa_matching_read(struct file *file, char __user *buf,
size_t size, loff_t *ppos)
{
- const char *matching = "pattern=aadfa perms=rwxamlz user:other";
+ const char *matching = "pattern=aadfa perms=rwxamlk/ user::other";
return simple_read_from_buffer(buf, size, ppos, matching,
strlen(matching));
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -99,7 +99,7 @@ static int aa_link_denied(struct aa_prof
/* Link always requires 'l' on the link for both parts of the pair.
* If a subset test is required a permission subset test of the
* perms for the link are done against the user:group:other of the
- * target's 'r', 'w', 'x', 'a', 'z', and 'm' permissions.
+ * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
*
* If the link has 'x', an exact match of all the execute flags
* ('i', 'u', 'p'). safe exec is treated as a subset of unsafe exec
@@ -388,7 +388,7 @@ static int aa_audit_base(struct aa_profi
audit_log_format(ab, " info=\"%s\"", sa->info);
if (sa->request_mask)
- aa_audit_file_mask(ab, "request_mask", sa->request_mask);
+ aa_audit_file_mask(ab, "requested_mask", sa->request_mask);
if (sa->denied_mask)
aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);

View file

@ -1,14 +0,0 @@
---
security/apparmor/lsm.c | 1 +
1 file changed, 1 insertion(+)
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -249,6 +249,7 @@ static int apparmor_sysctl(struct ctl_ta
}
out:
+ aa_put_profile(profile);
return error;
}

View file

@ -11,20 +11,21 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -104,6 +104,7 @@ config SECURITY_ROOTPLUG
If you are unsure how to answer this question, answer N.
@@ -126,6 +126,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
source security/selinux/Kconfig
source security/smack/Kconfig
+source security/apparmor/Kconfig
endmenu
--- a/security/Makefile
+++ b/security/Makefile
@@ -14,5 +14,6 @@ endif
obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o
@@ -16,6 +16,7 @@ obj-$(CONFIG_SECURITY) += security.o d
# Must precede capability.o in order to stack properly.
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += commoncap.o smack/built-in.o
+obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o

View file

@ -1,162 +0,0 @@
Change link to use pairs to provide tighter control of how links
can be made. The permission subset test is controled by an
extra flag of the link perm, this allows for compatibility with
old style links which have a broad pair, but also allows for
pairs to not require the subset test when needed.
The pairs are stored as two matches in the dfa seperated by the
null transition. Both matches must be made and have the link
perm set. If the second match has the AA_LINK_SUBSET_TEST perm
set, then the subset test is done.
The link keyword can be used or just the link mask
User side these pairs are expressed as follows
link [link_mask] linkname -> [subset_mask] targetname,
[link_mask] linkname -> [subset_mask] targetname,
link /linkname -> /targetname, #link to targetname, link is perm subset
if user:group:other link specification is desired then a user:group:other
mask containing only the link perm in the appropriate positions can be
specified
eg.
link l:: /linkname -> /targetname, # links to targetname if owned by
or
l:: /linkname -> /targetname,
Both the linkname and the target support full AppArmor globbing.
link l:: /** -> /**, # allow any link to target owned by user
to override the default subset test
l:: /linkname -> px /targetname,
Traditional AA style links are still supported and are mapped by the
parser into the newer link pair for the kernel, with the LINK_SUBSET_TEST
bits set.
/linkname rwl,
is mapped to
link /linkname -> /**,
/linkname rw,
---
security/apparmor/apparmor.h | 4 +++
security/apparmor/main.c | 45 ++++++++++++++++++++++++++++++++-----------
2 files changed, 38 insertions(+), 11 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -34,6 +34,7 @@
AA_MAY_LOCK | AA_EXEC_MMAP | \
AA_EXEC_UNSAFE | AA_EXEC_MOD_0 | \
AA_EXEC_MOD_1)
+#define AA_LINK_SUBSET_TEST 0x0020
#define AA_EXEC_UNCONFINED 0
#define AA_EXEC_INHERIT AA_EXEC_MOD_0
@@ -59,6 +60,9 @@
#define AA_USER_EXEC_MODS (AA_EXEC_MODIFIERS << AA_USER_SHIFT)
#define AA_OTHER_EXEC_MODS (AA_EXEC_MODIFIERS << AA_OTHER_SHIFT)
+#define AA_USER_EXEC_UNSAFE (AA_EXEC_UNSAFE << AA_USER_SHIFT)
+#define AA_OTHER_EXEC_UNSAFE (AA_EXEC_UNSAFE << AA_OTHER_SHIFT)
+
#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC)
#define AA_ALL_EXEC_MODS (AA_USER_EXEC_MODS | \
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -67,10 +67,27 @@ static int aa_link_denied(struct aa_prof
const char *target, int target_mode,
int *request_mask)
{
- int l_mode, t_mode, denied_mask;
+ unsigned int state;
+ int l_mode, t_mode, denied_mask = 0;
int link_mask = AA_MAY_LINK << target_mode;
- l_mode = aa_match(profile->file_rules, link);
+ *request_mask = link_mask;
+
+ l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state);
+ if (l_mode & link_mask) {
+ int mode;
+ /* test to see if target can be paired with link */
+ state = aa_dfa_null_transition(profile->file_rules, state);
+ mode = aa_match_state(profile->file_rules, state, target,
+ NULL);
+
+ if (!(mode & link_mask))
+ denied_mask |= link_mask;
+ if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
+ return denied_mask;
+ }
+
+ /* do link perm subset test */
t_mode = aa_match(profile->file_rules, target);
/* Ignore valid-profile-transition flags. */
@@ -79,23 +96,30 @@ static int aa_link_denied(struct aa_prof
*request_mask = l_mode | link_mask;
- /* Link always requires 'l' on the link, a subset for user:other
- * of the target's 'r', 'w', 'x', 'a', 'z', and 'm' permissions on
- * the link, and if the link has 'x', an exact match of all the
- * execute flags ('i', 'u', 'U', 'p', 'P').
+ /* Link always requires 'l' on the link for both parts of the pair.
+ * If a subset test is required a permission subset test of the
+ * perms for the link are done against the user:group:other of the
+ * target's 'r', 'w', 'x', 'a', 'z', and 'm' permissions.
+ *
+ * If the link has 'x', an exact match of all the execute flags
+ * ('i', 'u', 'p'). safe exec is treated as a subset of unsafe exec
*/
#define SUBSET_PERMS (AA_FILE_PERMS & ~AA_LINK_BITS)
- denied_mask = ~l_mode & link_mask;
+ denied_mask |= ~l_mode & link_mask;
if (l_mode & SUBSET_PERMS) {
denied_mask |= (l_mode & SUBSET_PERMS) & ~t_mode;
if (denied_mask & AA_EXEC_BITS)
denied_mask |= l_mode & AA_ALL_EXEC_MODS;
else if (l_mode & AA_EXEC_BITS) {
+ if (!(l_mode & AA_USER_EXEC_UNSAFE))
+ l_mode |= t_mode & AA_USER_EXEC_UNSAFE;
if (l_mode & AA_USER_EXEC &&
(l_mode & AA_USER_EXEC_MODS) !=
(t_mode & AA_USER_EXEC_MODS))
denied_mask |= AA_USER_EXEC |
(l_mode & AA_USER_EXEC_MODS);
+ if (!(l_mode & AA_OTHER_EXEC_UNSAFE))
+ l_mode |= t_mode & AA_OTHER_EXEC_UNSAFE;
if (l_mode & AA_OTHER_EXEC &&
(l_mode & AA_OTHER_EXEC_MODS) !=
(t_mode & AA_OTHER_EXEC_MODS))
@@ -703,15 +727,15 @@ int aa_link(struct aa_profile *profile,
struct dentry *link, struct vfsmount *link_mnt,
struct dentry *target, struct vfsmount *target_mnt)
{
- int error, check = 0;
+ int error;
struct aa_audit sa;
char *buffer = NULL, *buffer2 = NULL;
memset(&sa, 0, sizeof(sa));
sa.operation = "inode_link";
sa.gfp_mask = GFP_KERNEL;
- sa.name = aa_get_name(link, link_mnt, &buffer, check);
- sa.name2 = aa_get_name(target, target_mnt, &buffer2, check);
+ sa.name = aa_get_name(link, link_mnt, &buffer, 0);
+ sa.name2 = aa_get_name(target, target_mnt, &buffer2, 0);
if (IS_ERR(sa.name)) {
sa.error_code = PTR_ERR(sa.name);
@@ -723,7 +747,6 @@ int aa_link(struct aa_profile *profile,
}
if (sa.name && sa.name2) {
- sa.request_mask = AA_MAY_LINK;
sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2,
aa_inode_mode(target->d_inode),
&sa.request_mask);

View file

@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/lsm.c | 889 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 889 insertions(+)
security/apparmor/lsm.c | 895 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 895 insertions(+)
--- /dev/null
+++ b/security/apparmor/lsm.c
@@ -0,0 +1,889 @@
@@ -0,0 +1,895 @@
+/*
+ * Copyright (C) 1998-2007 Novell/SUSE
+ *
@ -294,7 +294,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ return ret;
+}
+
+static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
+static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
+ unsigned long flags, void *data)
+{
+ return aa_reject_syscall(current, GFP_KERNEL, "mount");
@ -526,14 +526,20 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+}
+
+static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags, struct file *file)
+ const char *name, const void *value,
+ size_t size, int flags, struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
+ int error = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
+ file);
+
+ if (!error)
+ error = aa_xattr_permission(dentry, mnt, "xattr set",
+ MAY_WRITE, file);
+ return error;
+}
+
+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, struct file *file)
+ const char *name, struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
+}
@ -545,7 +551,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+}
+
+static int apparmor_inode_removexattr(struct dentry *dentry,
+ struct vfsmount *mnt, char *name,
+ struct vfsmount *mnt, const char *name,
+ struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,

View file

@ -1,59 +0,0 @@
---
security/apparmor/main.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -172,15 +172,18 @@ escape:
static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
char **buffer, int check)
{
- char *name;
+ char *buf = NULL, *name;
int is_dir, size = 256;
is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
for (;;) {
- char *buf = kmalloc(size, GFP_KERNEL);
- if (!buf)
- return ERR_PTR(-ENOMEM);
+ char *b = krealloc(buf, size, GFP_KERNEL);
+
+ name = ERR_PTR(-ENOMEM);
+ if (!b)
+ break;
+ buf = b;
name = d_namespace_path(dentry, mnt, buf, size - is_dir);
@@ -195,8 +198,8 @@ static char *aa_get_name(struct dentry *
* This dentry is not connected to the
* namespace root -- reject access.
*/
- kfree(buf);
- return ERR_PTR(-ENOENT);
+ name = ERR_PTR(-ENOENT);
+ break;
}
if (is_dir && name[1] != '\0') {
/*
@@ -212,13 +215,15 @@ static char *aa_get_name(struct dentry *
return name;
}
if (PTR_ERR(name) != -ENAMETOOLONG)
- return name;
+ break;
- kfree(buf);
size <<= 1;
+ name = ERR_PTR(-ENAMETOOLONG);
if (size > apparmor_path_max)
- return ERR_PTR(-ENAMETOOLONG);
+ break;
}
+ kfree(buf);
+ return name;
}
static inline void aa_put_name_buffer(char *buffer)

View file

@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/main.c | 1479 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1479 insertions(+)
security/apparmor/main.c | 1478 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1478 insertions(+)
--- /dev/null
+++ b/security/apparmor/main.c
@@ -0,0 +1,1479 @@
@@ -0,0 +1,1478 @@
+/*
+ * Copyright (C) 2002-2007 Novell/SUSE
+ *
@ -941,7 +941,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ default:
+ /* all other indexes are named transitions */
+ index = AA_EXEC_INDEX(xmode);
+ if (index - 4 >= profile->exec_table_size) {
+ if (index - 4 > profile->exec_table_size) {
+ sa->info = "invalid named transition - exec failed";
+ sa->error_code = -EACCES;
+ new_profile = ERR_PTR(-EACCES);
@ -1154,7 +1154,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+
+static int do_change_profile(struct aa_profile *expected,
+ struct aa_namespace *ns, const char *name,
+ u64 cookie, int restore, struct aa_audit *sa)
+ u64 cookie, int restore, int hat,
+ struct aa_audit *sa)
+{
+ struct aa_profile *new_profile = NULL, *old_profile = NULL,
+ *previous_profile = NULL;
@ -1169,9 +1170,15 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+
+ new_profile = aa_find_profile(ns, name);
+ if (!new_profile && !restore) {
+ if (!PROFILE_COMPLAIN(expected))
+ if (!PROFILE_COMPLAIN(expected)) {
+ aa_free_task_context(new_cxt);
+ return -ENOENT;
+ }
+ new_profile = aa_dup_profile(ns->null_complain_profile);
+ } else if (new_profile && hat && !PROFILE_IS_HAT(new_profile)) {
+ aa_free_task_context(new_cxt);
+ aa_put_profile(new_profile);
+ return error;
+ }
+
+ cxt = lock_task_and_profiles(current, new_profile);
@ -1275,7 +1282,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ if (!profile || PROFILE_COMPLAIN(profile) ||
+ (ns == profile->ns &&
+ (aa_match(profile->file_rules, name, NULL) & AA_CHANGE_PROFILE)))
+ error = do_change_profile(profile, ns, name, 0, 0, &sa);
+ error = do_change_profile(profile, ns, name, 0, 0, 0, &sa);
+ else {
+ /* check for a rule with a namespace prepended */
+ aa_match_state(profile->file_rules, DFA_START, ns->name,
@ -1283,7 +1290,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ state = aa_dfa_null_transition(profile->file_rules, state);
+ if ((aa_match_state(profile->file_rules, state, name, NULL) &
+ AA_CHANGE_PROFILE))
+ error = do_change_profile(profile, ns, name, 0, 0,
+ error = do_change_profile(profile, ns, name, 0, 0, 0,
+ &sa);
+ else
+ /* no permission to transition to profile @name */
@ -1333,14 +1340,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+
+ if (hat_name) {
+ char *name, *profile_name;
+ if (!PROFILE_COMPLAIN(profile) &&
+ !(aa_match(profile->file_rules, hat_name, NULL)
+ & AA_CHANGE_HAT)) {
+ /* missing permission to change_hat is treated the
+ * same as a failed hat search */
+ error = -ENOENT;
+ goto out;
+ }
+
+ if (previous_profile)
+ profile_name = previous_profile->name;
@ -1353,11 +1352,11 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ goto out;
+ }
+ error = do_change_profile(profile, profile->ns, name, cookie,
+ 0, &sa);
+ 0, 1, &sa);
+ aa_put_name_buffer(name);
+ } else if (previous_profile)
+ error = do_change_profile(profile, profile->ns,
+ previous_profile->name, cookie, 1,
+ previous_profile->name, cookie, 1, 0,
+ &sa);
+ /* else ignore restores when there is no saved profile */
+

View file

@ -13,13 +13,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/Kconfig | 42 ++++
security/apparmor/Makefile | 13 +
security/apparmor/apparmor.h | 367 +++++++++++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 280 +++++++++++++++++++++++++++++++
security/apparmor/apparmor.h | 371 +++++++++++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 280 ++++++++++++++++++++++++++++++
security/apparmor/inline.h | 250 +++++++++++++++++++++++++++
security/apparmor/list.c | 156 +++++++++++++++++
security/apparmor/list.c | 174 +++++++++++++++++++
security/apparmor/locking.txt | 68 +++++++
security/apparmor/procattr.c | 195 +++++++++++++++++++++
8 files changed, 1371 insertions(+)
8 files changed, 1393 insertions(+)
--- /dev/null
+++ b/security/apparmor/Kconfig
@ -84,7 +84,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ $(call cmd,make-caps)
--- /dev/null
+++ b/security/apparmor/apparmor.h
@@ -0,0 +1,367 @@
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 1998-2007 Novell/SUSE
+ *
@ -208,6 +208,9 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ (apparmor_audit == 1 || \
+ ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit))
+
+#define PROFILE_IS_HAT(_profile) \
+ ((_profile) && (_profile)->flags.hat)
+
+/*
+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
+ * which is not related to profile accesses.
@ -281,6 +284,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ char **exec_table;
+ struct aa_dfa *file_rules;
+ struct {
+ int hat;
+ int complain;
+ int audit;
+ } flags;
@ -561,7 +565,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ size_t size, loff_t *ppos)
+{
+ const char *features = "file=3.0 capability=2.0 network=1.0 "
+ "change_hat=1.4 change_profile=1.0 "
+ "change_hat=1.5 change_profile=1.0 "
+ "aanamespaces=1.0";
+
+ return simple_read_from_buffer(buf, size, ppos, features,
@ -990,7 +994,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+#endif /* __INLINE_H__ */
--- /dev/null
+++ b/security/apparmor/list.c
@@ -0,0 +1,156 @@
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 1998-2007 Novell/SUSE
+ *
@ -1084,15 +1088,18 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ write_unlock(&profile_ns_list_lock);
+}
+
+static void *p_start(struct seq_file *f, loff_t *pos)
+
+static struct aa_profile *next_profile(struct aa_profile *profile)
+{
+ struct aa_profile *next = profile;
+ struct aa_namespace *ns;
+ struct aa_profile *profile;
+ loff_t l = *pos;
+ read_lock(&profile_ns_list_lock);
+ if (l--)
+ return NULL;
+ list_for_each_entry(ns, &profile_ns_list, list) {
+
+ list_for_each_entry_continue(next, &profile->ns->profiles, list)
+ return next;
+
+ ns = profile->ns;
+ read_unlock(&ns->lock);
+ list_for_each_entry_continue(ns, &profile_ns_list, list) {
+ read_lock(&ns->lock);
+ list_for_each_entry(profile, &ns->profiles, list)
+ return profile;
@ -1101,36 +1108,51 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ return NULL;
+}
+
+static void *p_start(struct seq_file *f, loff_t *pos)
+{
+ struct aa_namespace *ns;
+ loff_t l = *pos;
+
+ read_lock(&profile_ns_list_lock);
+ if (!list_empty(&profile_ns_list)) {
+ struct aa_profile *profile = NULL;
+ ns = list_first_entry(&profile_ns_list, typeof(*ns), list);
+ read_lock(&ns->lock);
+ if (!list_empty(&ns->profiles))
+ profile = list_first_entry(&ns->profiles,
+ typeof(*profile), list);
+ else
+ read_unlock(&ns->lock);
+ for ( ; profile && l > 0; l--)
+ profile = next_profile(profile);
+ return profile;
+ }
+ return NULL;
+}
+
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
+{
+ struct aa_profile *profile = (struct aa_profile *) p;
+ struct list_head *lh = profile->list.next;
+ struct aa_namespace *ns;
+
+ (*pos)++;
+ if (lh != &profile->ns->profiles)
+ return list_entry(lh, struct aa_profile, list);
+ profile = next_profile(profile);
+
+ lh = profile->ns->list.next;
+ read_unlock(&profile->ns->lock);
+ while (lh != &profile_ns_list) {
+ ns = list_entry(lh, struct aa_namespace, list);
+ read_lock(&ns->lock);
+ list_for_each_entry(profile, &ns->profiles, list)
+ return profile;
+ read_unlock(&ns->lock);
+ lh = ns->list.next;
+ }
+ return NULL;
+}
+
+static void p_stop(struct seq_file *f, void *v)
+static void p_stop(struct seq_file *f, void *p)
+{
+ struct aa_profile *profile = (struct aa_profile *) p;
+
+ if (profile)
+ read_unlock(&profile->ns->lock);
+ read_unlock(&profile_ns_list_lock);
+}
+
+static int seq_show_profile(struct seq_file *f, void *v)
+static int seq_show_profile(struct seq_file *f, void *p)
+{
+ struct aa_profile *profile = (struct aa_profile *)v;
+ struct aa_profile *profile = (struct aa_profile *)p;
+
+ if (profile->ns == default_namespace)
+ seq_printf(f, "%s (%s)\n", profile->name,
+ PROFILE_COMPLAIN(profile) ? "complain" : "enforce");

View file

@ -812,7 +812,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ /* per profile debug flags (complain, audit) */
+ if (!aa_is_nameX(e, AA_STRUCT, "flags"))
+ goto fail;
+ if (!aa_is_u32(e, NULL, NULL))
+ if (!aa_is_u32(e, &(profile->flags.hat), NULL))
+ goto fail;
+ if (!aa_is_u32(e, &(profile->flags.complain), NULL))
+ goto fail;

View file

@ -40,7 +40,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
/*
* We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
@@ -208,6 +210,9 @@ struct aa_profile {
@@ -212,6 +214,9 @@ struct aa_profile {
struct list_head task_contexts;
spinlock_t lock;
unsigned long int_flags;
@ -50,7 +50,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
};
extern struct list_head profile_ns_list;
@@ -254,6 +259,7 @@ struct aa_audit {
@@ -258,6 +263,7 @@ struct aa_audit {
int request_mask, denied_mask, audit_mask;
struct iattr *iattr;
pid_t task, parent;
@ -58,7 +58,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int error_code;
};
@@ -315,6 +321,9 @@ extern void aa_change_task_context(struc
@@ -319,6 +325,9 @@ extern void aa_change_task_context(struc
struct aa_profile *previous_profile);
extern int aa_may_ptrace(struct aa_task_context *cxt,
struct aa_profile *tracee);

View file

@ -36,7 +36,7 @@ linux limitations.
#include <linux/socket.h>
#include <net/sock.h>
@@ -136,6 +137,18 @@ extern unsigned int apparmor_path_max;
@@ -139,6 +140,18 @@ extern unsigned int apparmor_path_max;
#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
@ -55,7 +55,7 @@ linux limitations.
struct aa_profile;
/* struct aa_namespace - namespace for a set of profiles
@@ -170,6 +183,8 @@ struct aa_namespace {
@@ -173,6 +186,8 @@ struct aa_namespace {
* @audit_caps: caps that are to be audited
* @quiet_caps: caps that should not be audited
* @capabilities: capabilities granted by the process
@ -64,7 +64,7 @@ linux limitations.
* @count: reference count of the profile
* @task_contexts: list of tasks confined by profile
* @lock: lock for the task_contexts list
@@ -206,6 +221,9 @@ struct aa_profile {
@@ -210,6 +225,9 @@ struct aa_profile {
kernel_cap_t audit_caps;
kernel_cap_t quiet_caps;
@ -74,7 +74,7 @@ linux limitations.
struct kref count;
struct list_head task_contexts;
spinlock_t lock;
@@ -257,6 +275,7 @@ struct aa_audit {
@@ -261,6 +279,7 @@ struct aa_audit {
const char *name2;
const char *name3;
int request_mask, denied_mask, audit_mask;
@ -82,7 +82,7 @@ linux limitations.
struct iattr *iattr;
pid_t task, parent;
int family, type, protocol;
@@ -324,6 +343,10 @@ extern int aa_may_ptrace(struct aa_task_
@@ -328,6 +347,10 @@ extern int aa_may_ptrace(struct aa_task_
extern int aa_net_perm(struct aa_profile *profile, char *operation,
int family, int type, int protocol);
extern int aa_revalidate_sk(struct sock *sk, char *operation);
@ -98,7 +98,7 @@ linux limitations.
@@ -105,7 +105,7 @@ static ssize_t aa_features_read(struct f
{
const char *features = "file=3.0 capability=2.0 network=1.0 "
"change_hat=1.4 change_profile=1.0 "
"change_hat=1.5 change_profile=1.0 "
- "aanamespaces=1.0";
+ "aanamespaces=1.0 rlimit=1.0";
@ -287,7 +287,7 @@ linux limitations.
new_profile = old_profile;
goto cleanup;
}
@@ -1296,6 +1386,12 @@ static int do_change_profile(struct aa_p
@@ -1303,6 +1393,12 @@ static int do_change_profile(struct aa_p
goto out;
}
@ -300,7 +300,7 @@ linux limitations.
if (new_profile == ns->null_complain_profile)
aa_audit_hint(cxt->profile, sa);
@@ -1482,17 +1578,18 @@ struct aa_profile *__aa_replace_profile(
@@ -1481,17 +1577,18 @@ struct aa_profile *__aa_replace_profile(
cxt = lock_task_and_profiles(task, profile);
if (unlikely(profile && profile->isstale)) {
@ -327,7 +327,7 @@ linux limitations.
}
if (cxt)
@@ -1500,8 +1597,15 @@ struct aa_profile *__aa_replace_profile(
@@ -1499,8 +1596,15 @@ struct aa_profile *__aa_replace_profile(
aa_change_task_context(task, new_cxt, profile, 0, NULL);
task_unlock(task);
@ -343,7 +343,7 @@ linux limitations.
}
/**
@@ -1566,6 +1670,7 @@ void aa_change_task_context(struct task_
@@ -1565,6 +1669,7 @@ void aa_change_task_context(struct task_
if (old_cxt) {
list_del_init(&old_cxt->list);
@ -351,7 +351,7 @@ linux limitations.
call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
}
if (new_cxt) {
@@ -1577,6 +1682,7 @@ void aa_change_task_context(struct task_
@@ -1576,6 +1681,7 @@ void aa_change_task_context(struct task_
new_cxt->cookie = cookie;
new_cxt->task = task;
new_cxt->profile = aa_dup_profile(profile);
@ -384,7 +384,7 @@ linux limitations.
static size_t aa_is_array(struct aa_ext *e, const char *name)
{
void *pos = e->pos;
@@ -311,6 +327,39 @@ fail:
@@ -312,6 +328,39 @@ fail:
return 0;
}
@ -401,7 +401,7 @@ linux limitations.
+ profile->rlimits.mask = tmp;
+
+ size = aa_is_array(e, NULL);
+ if (size != RLIM_NLIMITS)
+ if (size > RLIM_NLIMITS)
+ goto fail;
+ for (i = 0; i < size; i++) {
+ u64 tmp = 0;
@ -424,7 +424,7 @@ linux limitations.
/**
* aa_unpack_profile - unpack a serialized profile
* @e: serialized data extent information
@@ -354,6 +403,9 @@ static struct aa_profile *aa_unpack_prof
@@ -355,6 +404,9 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_u32(e, &(profile->set_caps), NULL))
goto fail;
@ -434,7 +434,7 @@ linux limitations.
size = aa_is_array(e, "net_allowed_af");
if (size) {
if (size > AF_MAX)
@@ -613,6 +665,8 @@ ssize_t aa_replace_profile(void *udata,
@@ -614,6 +666,8 @@ ssize_t aa_replace_profile(void *udata,
sa.operation = "profile_load";
goto out;
}
@ -443,7 +443,7 @@ linux limitations.
/*
* Replacement needs to allocate a new aa_task_context for each
* task confined by old_profile. To do this the profile locks
@@ -633,6 +687,7 @@ ssize_t aa_replace_profile(void *udata,
@@ -634,6 +688,7 @@ ssize_t aa_replace_profile(void *udata,
task_lock(task);
task_replace(task, new_cxt, new_profile);
task_unlock(task);
@ -451,7 +451,7 @@ linux limitations.
new_cxt = NULL;
}
unlock_both_profiles(old_profile, new_profile);
@@ -655,6 +710,7 @@ out:
@@ -656,6 +711,7 @@ out:
*
* remove a profile from the profile list and all aa_task_context references
* to said profile.

View file

@ -1,73 +0,0 @@
---
security/apparmor/apparmor.h | 1 +
security/apparmor/match.c | 9 +++++++--
security/apparmor/match.h | 2 ++
3 files changed, 10 insertions(+), 2 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -87,6 +87,7 @@
AA_AUDIT_FIELD)
#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_SHARED_PERMS)
+#define AA_VALID_PERM2_MASK 0x0fffffff
#define AA_SECURE_EXEC_NEEDED 1
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -83,6 +83,7 @@ int unpack_dfa(struct aa_dfa *dfa, void
switch(table->td_id) {
case YYTD_ID_ACCEPT:
+ case YYTD_ID_ACCEPT2:
case YYTD_ID_BASE:
dfa->tables[table->td_id - 1] = table;
if (table->td_flags != YYTD_DATA32)
@@ -134,7 +135,8 @@ int verify_dfa(struct aa_dfa *dfa)
int error = -EPROTO;
/* check that required tables exist */
- if (!(dfa->tables[YYTD_ID_ACCEPT -1 ] &&
+ if (!(dfa->tables[YYTD_ID_ACCEPT - 1] &&
+ dfa->tables[YYTD_ID_ACCEPT2 - 1] &&
dfa->tables[YYTD_ID_DEF - 1] &&
dfa->tables[YYTD_ID_BASE - 1] &&
dfa->tables[YYTD_ID_NXT - 1] &&
@@ -144,7 +146,8 @@ int verify_dfa(struct aa_dfa *dfa)
/* accept.size == default.size == base.size */
state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
- state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen))
+ state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen &&
+ state_count == dfa->tables[YYTD_ID_ACCEPT2 - 1]->td_lolen))
goto out;
/* next.size == chk.size */
@@ -177,6 +180,8 @@ int verify_dfa(struct aa_dfa *dfa)
if (mode & ~AA_VALID_PERM_MASK)
goto out;
+ if (ACCEPT_TABLE2(dfa)[i] & ~AA_VALID_PERM2_MASK)
+ goto out;
/* if any exec modifier is set MAY_EXEC must be set */
if ((mode & AA_USER_EXEC_TYPE) && !(mode & AA_USER_EXEC))
--- a/security/apparmor/match.h
+++ b/security/apparmor/match.h
@@ -39,6 +39,7 @@ struct table_set_header {
#define YYTD_ID_DEF 4
#define YYTD_ID_EC 5
#define YYTD_ID_META 6
+#define YYTD_ID_ACCEPT2 7
#define YYTD_ID_NXT 8
@@ -60,6 +61,7 @@ struct table_header {
#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
+#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 -1]->td_data))
struct aa_dfa {
struct table_header *tables[YYTD_ID_NXT];

View file

@ -1,141 +0,0 @@
---
Documentation/lsm/AppArmor-Security-Goal.txt | 134 +++++++++++++++++++++++++++
1 file changed, 134 insertions(+)
--- /dev/null
+++ b/Documentation/lsm/AppArmor-Security-Goal.txt
@@ -0,0 +1,134 @@
+AppArmor Security Goal
+Crispin Cowan, PhD
+MercenaryLinux.com
+
+This document specifies the security goal that AppArmor is intended to
+achieve, so that users can evaluate whether AppArmor will meet their
+needs, and kernel developers can evaluate whether AppArmor is living up
+to its claims. This document is *not* a general purpose explanation of
+how AppArmor works, nor is it an explanation for why one might want to
+use AppArmor rather than some other system.
+
+AppArmor is intended to limit system damage from attackers exploiting
+vulnerabilities in applications that the system hosts. The threat is
+that an attacker can cause a vulnerable application to do something
+unexpected and undesirable. AppArmor addresses this threat by confining
+the application to access only the resources it needs to access to
+execute properly, effectively imposing "least privilege" execution on
+the application.
+
+Applications interact with the rest of the system via resources
+including files, interprocess communication, networking, capabilities,
+and execution of other applications. The purpose of least privilege is
+to bound the damage that a malicious user or code can do by removing
+access to resources that the application does not need for its intended
+function. This is true for all access control systems, including AppArmor.
+
+The "attacker" is someone trying to gain the privileges of a process for
+themselves. For instance, a policy for a web server might grant read
+only access to most web documents, preventing an attacker who can
+corrupt the web server from defacing the web pages. A web server has
+access to the web server's local file system, and a network attacker
+trying to hack the web server does not have such file access. An e-mail
+attacker attempting to infect the recipient of the e-mail does not have
+access to the files that the victim user's mail client does. By limiting
+the scope of access for an application, AppArmor can limit the damage an
+attacker can do by exploiting vulnerabilities in applications.
+
+An "application" is one or more related processes performing a function,
+e.g. the gang of processes that constitute an Apache web server, or a
+Postfix mail server. AppArmor *only* confines processes that the
+AppArmor policy says it should confine, and other processes are
+permitted to do anything that DAC permits. This is sometimes known as a
+targeted security policy.
+
+AppArmor does not provide a "default" policy that applies to all
+processes. So to defend an entire host, you have to piece-wise confine
+each process that is exposed to potential attack. For instance, to
+defend a system against network attack, place AppArmor profiles around
+every application that accesses the network. This limits the damage a
+network attacker can do to the file system to only those files granted
+by the profiles for the network-available applications. Similarly, to
+defend a system against attack from the console, place AppArmor profiles
+around every application that accessed the keyboard and mouse. The
+system is "defended" in that the worst the attacker can do to corrupt
+the system is limited to the transitive closure of what the confined
+processes are allowed to access.
+
+AppArmor currently mediates access to files, ability to use POSIX.1e
+Capabilities, and coarse-grained control on network access. This is
+sufficient to prevent a confined process from *directly* corrupting the
+file system. It is not sufficient to prevent a confined process from
+*indirectly* corrupting the system by influencing some other process to
+do the dirty deed. But to do so requires a complicit process that can be
+manipulated through another channel such as IPC. A "complicit" process
+is either a malicious process the attacker somehow got control of, or is
+a process that is actively listening to IPC of some kind and can be
+corrupted via IPC.
+
+The only IPC that AppArmor mediates is access to named sockets, FIFOs,
+etc. that appear in the file system name space, a side effect of
+AppArmor's file access mediation. Future versions of AppArmor will
+mediate more resources, including finer grained network access controls,
+and controls on various forms of IPC.
+
+AppArmor specifies the programs to be confined and the resources they
+can access in a syntax similar to how users are accustomed to accessing
+those resources. So file access controls are specified using absolute
+paths with respect to the name space the process is in. POSIX.1e
+capabilities are specified by name. Network access controls currently
+are specified by simply naming the protocol that can be used e.g. tcp,
+udp, and in the future will be more general, resembling firewall rules.
+
+Thus the AppArmor security goal should be considered piecewise from the
+point of view of a single confined process: that process should only be
+able to access the resources specified in its profile:
+
+ * can only access files that are reachable in its name space by path
+ names matching its profile, and only with the permitted modes:
+ read, append, write, memory map, execute, and link
+ * can only use the POSIX.1e capabilities listed in the profile
+ * can only perform the network operations listed in the profile
+
+Security issues that AppArmor explicitly does *not* address:
+
+ * Processes that are not confined by AppArmor are not restricted in
+ any way by AppArmor. If an unconfined process is considered an
+ unacceptable threat, then confine additional applications until
+ adequate security is achieved.
+ * A process that is not permitted to directly access a resource can
+ influence some other process that does have access to the resource
+ may do so, if the "influence" is a permitted action.
+ * A confined process may only access a file if it has at least one
+ of the files aliases specified in its profile. If a file alias is
+ not specified in the profile then it can not be accessed by that
+ path. The creation of aliases needs to be tightly controlled in
+ confined applications, hard links creation should be limited to
+ provide adequate security.
+ * A confined process can operate on a file descriptor passed to it
+ by an unconfined process, even if it manipulates a file not in the
+ confined process's profile. To block this attack, confine the
+ process that passed the file descriptor.
+ * Process activities not currently mediated by AppArmor are
+ permitted, e.g. confined processes can perform any IPC that DAC
+ permits, other than signals as mediated by CAP_KILL.
+ * Manipulating AppArmor policy requires being both root privileged
+ and not being confined by AppArmor, thus there is explicitly no
+ capability for non-privileged users to change AppArmor policy.
+ * AppArmor confines processes if they are children of a confined
+ process, or if the name of the exec'd child matches the name of an
+ AppArmor profile. Another process could copy a program to a
+ different path name and then execute it without confinement, but
+ the other process would have to have permission to do so in the
+ first place. To prevent this, confine the other process and
+ additional applications until adequate security is achieved.
+ * Mount and namespace manipulations can be used to arbitrarily
+ change the pathnames that files appear at, and thus completely
+ bypass AppArmor policy. To prevent this, processes confined by
+ AppArmor are currently not permitted to call mount or manipulate
+ name spaces at all. A future development may provide more granular
+ controls on mount and namespace manipulations.
+ * AppArmor does not slice bread, cure cancer, bring world peace, or
+ provide perfect security. This list may be expanded :-)
+
+

View file

@ -0,0 +1,212 @@
From: John Johnansen <jjohansen@suse.de>
Subject: allow apparmor to stack with dazuko
Patch-mainline: no
References: 300965
Allow AppArmor to stack with dazuko so that the clamav virus
scanner can be used on an AppArmored machine.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
security/apparmor/apparmor.h | 2
security/apparmor/apparmorfs.c | 2
security/apparmor/lsm.c | 101 ++++++++++++++++++++++++++++++++++++-----
3 files changed, 92 insertions(+), 13 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -354,7 +354,7 @@ extern void aa_set_rlimits(struct task_s
/* lsm.c */
extern int apparmor_initialized;
-extern void info_message(const char *str);
+extern void info_message(const char *str, const char *name);
extern void apparmor_disable(void);
/* list.c */
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -266,7 +266,7 @@ int create_apparmorfs(void)
goto error;
/* Report that AppArmor fs is enabled */
- info_message("AppArmor Filesystem Enabled");
+ info_message("AppArmor Filesystem Enabled", "");
return 0;
error:
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -26,6 +26,20 @@
/* Flag indicating whether initialization completed */
int apparmor_initialized = 0;
+/* point to the apparmor module */
+struct module *aa_module = NULL;
+
+/* secondary ops if apparmor is stacked */
+static struct security_operations *aa_secondary_ops = NULL;
+static DEFINE_MUTEX(aa_secondary_lock);
+
+#define AA_SECONDARY(FN, ARGS...) \
+ ({ \
+ struct security_operations *__f1; \
+ __f1 = rcu_dereference(aa_secondary_ops); \
+ (unlikely(__f1) && __f1->FN) ? __f1->FN(ARGS) : 0; \
+ })
+
static int param_set_aabool(const char *val, struct kernel_param *kp);
static int param_get_aabool(char *buffer, struct kernel_param *kp);
#define param_check_aabool(name, p) __param_check(name, p, int)
@@ -452,19 +466,25 @@ out:
static int apparmor_inode_permission(struct inode *inode, int mask,
struct nameidata *nd)
{
- int check = 0;
+ int check = 0, error = 0;
if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
- return 0;
+ goto out;
mask = aa_mask_permissions(mask);
if (S_ISDIR(inode->i_mode)) {
check |= AA_CHECK_DIR;
/* allow traverse accesses to directories */
mask &= ~MAY_EXEC;
}
- return aa_permission("inode_permission", inode, nd->path.dentry,
- nd->path.mnt,
- mask, check);
+ error = aa_permission("inode_permission", inode, nd->path.dentry,
+ nd->path.mnt,
+ mask, check);
+
+out:
+ if (!error)
+ error = AA_SECONDARY(inode_permission, inode, mask, nd);
+
+ return error;
}
static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
@@ -882,6 +902,61 @@ static int apparmor_task_setrlimit(unsig
return error;
}
+int apparmor_register_subsecurity(const char *name,
+ struct security_operations *ops)
+{
+ int error = 0;
+
+ if (mutex_lock_interruptible(&aa_secondary_lock))
+ return -ERESTARTSYS;
+
+ /* allow dazuko and capability to stack. The stacking with
+ * capability is not needed since apparmor already composes
+ * capability using common cap.
+ */
+ if (!aa_secondary_ops && (strcmp(name, "dazuko") == 0 ||
+ strcmp(name, "capability") == 0)){
+ /* The apparmor module needs to be pinned while a secondary is
+ * registered
+ */
+ if (try_module_get(aa_module)) {
+ aa_secondary_ops = ops;
+ info_message("Registered secondary security module",
+ name);
+ } else {
+ error = -EINVAL;
+ }
+ } else {
+ info_message("Unable to register %s as a secondary security "
+ "module", name);
+ error = -EPERM;
+ }
+ mutex_unlock(&aa_secondary_lock);
+ return error;
+}
+
+int apparmor_unregister_subsecurity(const char *name,
+ struct security_operations *ops)
+{
+ int error = 0;
+
+ if (mutex_lock_interruptible(&aa_secondary_lock))
+ return -ERESTARTSYS;
+
+ if (aa_secondary_ops && aa_secondary_ops == ops) {
+ rcu_assign_pointer(aa_secondary_ops, NULL);
+ synchronize_rcu();
+ module_put(aa_module);
+ info_message("Unregistered secondary security module", name);
+ } else {
+ info_message("Unable to unregister secondary security module",
+ name);
+ error = -EPERM;
+ }
+ mutex_unlock(&aa_secondary_lock);
+ return error;
+}
+
struct security_operations apparmor_ops = {
.ptrace = apparmor_ptrace,
.capget = cap_capget,
@@ -928,6 +1003,8 @@ struct security_operations apparmor_ops
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
+ .register_security = apparmor_register_subsecurity,
+
.socket_create = apparmor_socket_create,
.socket_post_create = apparmor_socket_post_create,
.socket_bind = apparmor_socket_bind,
@@ -943,13 +1020,14 @@ struct security_operations apparmor_ops
.socket_shutdown = apparmor_socket_shutdown,
};
-void info_message(const char *str)
+void info_message(const char *str, const char *name)
{
struct aa_audit sa;
memset(&sa, 0, sizeof(sa));
sa.gfp_mask = GFP_KERNEL;
sa.info = str;
- printk(KERN_INFO "AppArmor: %s\n", str);
+ sa.name = name;
+ printk(KERN_INFO "AppArmor: %s %s\n", str, name);
if (audit_enabled)
aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
}
@@ -959,7 +1037,7 @@ static int __init apparmor_init(void)
int error;
if (!apparmor_enabled) {
- info_message("AppArmor disabled by boottime parameter\n");
+ info_message("AppArmor disabled by boottime parameter", "");
return 0;
}
@@ -981,9 +1059,10 @@ static int __init apparmor_init(void)
/* Report that AppArmor successfully initialized */
apparmor_initialized = 1;
if (apparmor_complain)
- info_message("AppArmor initialized: complainmode enabled");
+ info_message("AppArmor initialized: complainmode enabled",
+ NULL);
else
- info_message("AppArmor initialized");
+ info_message("AppArmor initialized", NULL);
return error;
@@ -1021,7 +1100,7 @@ void apparmor_disable(void)
apparmor_initialized = 0;
- info_message("AppArmor protection removed");
+ info_message("AppArmor protection removed", NULL);
}
MODULE_DESCRIPTION("AppArmor process confinement");

View file

@ -1,18 +0,0 @@
---
security/apparmor/main.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -159,8 +159,10 @@ static int aa_audit_base(struct aa_profi
return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
}
+ audit_log_format(ab, " type=%d", type);
+
if (sa->operation)
- audit_log_format(ab, "operation=\"%s\"", sa->operation);
+ audit_log_format(ab, " operation=\"%s\"", sa->operation);
if (sa->info) {
audit_log_format(ab, " info=\"%s\"", sa->info);

View file

@ -1,16 +0,0 @@
---
security/apparmor/main.c | 3 +++
1 file changed, 3 insertions(+)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -405,6 +405,9 @@ static int aa_audit_base(struct aa_profi
if (sa->denied_mask)
aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);
+ if (sa->request_mask)
+ audit_log_format(ab, " fsuid=%d", current->fsuid);
+
if (sa->iattr) {
struct iattr *iattr = sa->iattr;

View file

@ -1,87 +0,0 @@
---
security/apparmor/apparmor.h | 10 ++++++++++
security/apparmor/apparmorfs.c | 4 ++--
security/apparmor/lsm.c | 15 ++++++---------
security/apparmor/module_interface.c | 2 ++
4 files changed, 20 insertions(+), 11 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -158,8 +158,17 @@ struct aa_namespace {
* @file_rules: dfa containing the profiles file rules
* @flags: flags controlling profile behavior
* @isstale: flag indicating if profile is stale
+ * @set_caps: capabilities that are being set
+ * @capabilities: capabilities mask
+ * @audit_caps: caps that are to be audited
+ * @quiet_caps: caps that should not be audited
* @capabilities: capabilities granted by the process
* @count: reference count of the profile
+ * @task_contexts: list of tasks confined by profile
+ * @lock: lock for the task_contexts list
+ * @network_families: basic network permissions
+ * @audit_network: which network permissions to force audit
+ * @quiet_network: which network permissions to quiet rejects
*
* The AppArmor profile contains the basic confinement data. Each profile
* has a name, and all nonstale profile are in a profile namespace.
@@ -183,6 +192,7 @@ struct aa_profile {
} flags;
int isstale;
+ kernel_cap_t set_caps;
kernel_cap_t capabilities;
kernel_cap_t audit_caps;
kernel_cap_t quiet_caps;
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -103,8 +103,8 @@ static struct file_operations apparmorfs
static ssize_t aa_features_read(struct file *file, char __user *buf,
size_t size, loff_t *ppos)
{
- const char *features = "file=3.0 capability=1.0 network=1.0 "
- "change_hat=1.3 change_profile=1.0 "
+ const char *features = "file=3.0 capability=2.0 network=1.0 "
+ "change_hat=1.4 change_profile=1.0 "
"aanamespaces=1.0";
return simple_read_from_buffer(buf, size, ppos, features,
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -210,19 +210,16 @@ static int apparmor_ptrace(struct task_s
static int apparmor_capable(struct task_struct *task, int cap)
{
int error;
+ struct aa_task_context *cxt;
/* cap_capable returns 0 on success, else -EPERM */
error = cap_capable(task, cap);
- if (!error) {
- struct aa_task_context *cxt;
-
- rcu_read_lock();
- cxt = aa_task_context(task);
- if (cxt)
- error = aa_capability(cxt, cap);
- rcu_read_unlock();
- }
+ rcu_read_lock();
+ cxt = aa_task_context(task);
+ if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap)))
+ error = aa_capability(cxt, cap);
+ rcu_read_unlock();
return error;
}
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -316,6 +316,8 @@ static struct aa_profile *aa_unpack_prof
goto fail;
if (!aa_is_u32(e, &(profile->quiet_caps), NULL))
goto fail;
+ if (!aa_is_u32(e, &(profile->set_caps), NULL))
+ goto fail;
size = aa_is_array(e, "net_allowed_af");
if (size) {

View file

@ -1,95 +0,0 @@
This patch removes magic cookies from the aa_change_profile interface, making
it a true one-way transition.
It also fixes a refcounting bug with previous_profile by virtue of removing
the broken code entirely.
Signed-off-by: Kenny Graunke <kgraunke@novell.com>
Signed-off-by: Seth Arnold <seth.arnold@suse.de>
---
security/apparmor/apparmor.h | 2 +-
security/apparmor/main.c | 21 +++++++--------------
security/apparmor/procattr.c | 9 +--------
3 files changed, 9 insertions(+), 23 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -211,7 +211,7 @@ extern int aa_clone(struct task_struct *
extern int aa_register(struct linux_binprm *bprm);
extern void aa_release(struct task_struct *task);
extern int aa_change_hat(const char *id, u64 hat_magic);
-extern int aa_change_profile(const char *name, u64 cookie);
+extern int aa_change_profile(const char *name);
extern struct aa_profile *__aa_find_profile(const char *name,
struct list_head *list);
extern struct aa_profile *__aa_replace_profile(struct task_struct *task,
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -1110,20 +1110,18 @@ out:
}
/**
- * aa_change_profile - change profile to/from previous stored profile
+ * aa_change_profile - perform a one-way profile transition
* @name: name of profile to change to
- * @cookie: magic value to validate the profile change
*
- * Change to new profile @name, and store the @cookie in the current task
- * context. If the new @name is %NULL and the @cookie matches that
- * stored in the current task context, return to the previous profile.
+ * Change to new profile @name. Unlike with hats, there is no way
+ * to change back.
*
* Returns %0 on success, error otherwise.
*/
-int aa_change_profile(const char *name, u64 cookie)
+int aa_change_profile(const char *name)
{
struct aa_task_context *cxt;
- struct aa_profile *profile, *previous_profile;
+ struct aa_profile *profile;
struct aa_audit sa;
int error = 0;
@@ -1139,7 +1137,6 @@ repeat:
return -EPERM;
}
profile = aa_dup_profile(cxt->profile);
- previous_profile = aa_dup_profile(cxt->previous_profile);
task_unlock(current);
if (name) {
@@ -1150,13 +1147,9 @@ repeat:
aa_put_profile(profile);
return -EACCES;
}
- error = do_change_profile(profile, name, cookie, 0, &sa);
- } else if (previous_profile)
- error = do_change_profile(profile, previous_profile->name,
- cookie, 1, &sa);
- /* else ignore restores when there is no saved profile */
+ error = do_change_profile(profile, name, 0, 0, &sa);
+ }
- aa_put_profile(previous_profile);
aa_put_profile(profile);
if (error == -ESTALE)
goto repeat;
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -87,14 +87,7 @@ int aa_setprocattr_changehat(char *args)
int aa_setprocattr_changeprofile(char *args)
{
- char *name;
- u64 cookie;
-
- name = split_token_from_name("change_profile", args, &cookie);
- if (IS_ERR(name))
- return PTR_ERR(name);
-
- return aa_change_profile(name, cookie);
+ return aa_change_profile(args);
}
int aa_setprocattr_setprofile(struct task_struct *task, char *args)

View file

@ -9,30 +9,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 6 +++---
fs/namespace.c | 27 +++++++++++++++++++++++++++
include/linux/dcache.h | 2 ++
fs/namespace.c | 29 +++++++++++++++++++++++++++++
include/linux/mount.h | 2 ++
4 files changed, 34 insertions(+), 3 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1782,9 +1782,9 @@ shouldnt_be_hashed:
*
* Returns the buffer or an error code.
*/
-static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
- struct dentry *root, struct vfsmount *rootmnt,
- char *buffer, int buflen, int fail_deleted)
+char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ struct dentry *root, struct vfsmount *rootmnt,
+ char *buffer, int buflen, int fail_deleted)
{
int namelen, is_slash, vfsmount_locked = 0;
2 files changed, 31 insertions(+)
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1883,3 +1883,30 @@ void __put_mnt_ns(struct mnt_namespace *
@@ -2351,3 +2351,32 @@ void __put_mnt_ns(struct mnt_namespace *
release_mounts(&umount_list);
kfree(ns);
}
@ -40,47 +23,37 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
+char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ char *buf, int buflen)
+{
+ struct vfsmount *rootmnt, *nsrootmnt = NULL;
+ struct dentry *root = NULL;
+ struct path root, ns_root = { };
+ struct path path = { .mnt = vfsmnt, .dentry = dentry };
+ char *res;
+
+ read_lock(&current->fs->lock);
+ rootmnt = mntget(current->fs->rootmnt);
+ root = current->fs->root;
+ path_get(&current->fs->root);
+ read_unlock(&current->fs->lock);
+ spin_lock(&vfsmount_lock);
+ if (rootmnt->mnt_ns)
+ nsrootmnt = mntget(rootmnt->mnt_ns->root);
+ if (root.mnt)
+ ns_root.mnt = mntget(root.mnt->mnt_ns->root);
+ if (ns_root.mnt)
+ ns_root.dentry = dget(ns_root.mnt->mnt_root);
+ spin_unlock(&vfsmount_lock);
+ mntput(rootmnt);
+ if (nsrootmnt)
+ root = dget(nsrootmnt->mnt_root);
+ res = __d_path(dentry, vfsmnt, root, nsrootmnt, buf, buflen, 1);
+ dput(root);
+ mntput(nsrootmnt);
+ res = __d_path(&path, &ns_root, buf, buflen,
+ D_PATH_FAIL_DELETED | D_PATH_DISCONNECT);
+ path_put(&root);
+ path_put(&ns_root);
+
+ /* Prevent empty path for lazily unmounted filesystems. */
+ if (!IS_ERR(res) && *res == '\0')
+ *--res = '.';
+ return res;
+}
+EXPORT_SYMBOL(d_namespace_path);
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -300,6 +300,8 @@ extern int d_validate(struct dentry *, s
*/
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+extern char *__d_path(struct dentry *, struct vfsmount *, struct dentry *,
+ struct vfsmount *, char *, int, int);
extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
/* Allocation counts.. */
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -103,5 +103,7 @@ extern void shrink_submounts(struct vfsm
@@ -113,4 +113,6 @@ extern void mark_mounts_for_expiry(struc
extern spinlock_t vfsmount_lock;
extern dev_t name_to_dev_t(char *name);
+extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
+
#endif
#endif /* _LINUX_MOUNT_H */

View file

@ -8,13 +8,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
fs/namei.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1147,25 +1147,24 @@ static int fastcall do_path_lookup(int d
nd->dentry = dget(fs->pwd);
@@ -1153,24 +1153,21 @@ static int do_path_lookup(int dfd, const
path_get(&fs->pwd);
read_unlock(&fs->lock);
} else {
- struct dentry *dentry;
@ -25,23 +25,18 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
goto out_fail;
- dentry = file->f_path.dentry;
+ nd->dentry = file->f_path.dentry;
+ nd->mnt = file->f_path.mnt;
+ nd->path = file->f_path;
retval = -ENOTDIR;
- if (!S_ISDIR(dentry->d_inode->i_mode))
+ if (!S_ISDIR(nd->dentry->d_inode->i_mode))
+ if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
goto fput_fail;
- retval = file_permission(file, MAY_EXEC);
+ retval = vfs_permission(nd, MAY_EXEC);
retval = file_permission(file, MAY_EXEC);
if (retval)
goto fput_fail;
- nd->mnt = mntget(file->f_path.mnt);
- nd->dentry = dget(dentry);
+ mntget(nd->mnt);
+ dget(nd->dentry);
- nd->path = file->f_path;
path_get(&file->f_path);
fput_light(file, fput_needed);
}

View file

@ -1,42 +0,0 @@
From: Andreas Gruenbacher <agruen@use.de>
Subject: Check for NULL nameidata in ecryptfs_d_revalidate
Some filesystems like nfsd and ecryptfs use lookup_one_len() on other
filesystems. This causes d_revalidate() calls with nd == NULL through
__lookup_hash() and cached_lookup(), so we need to check for NULL
nameidata.
Signed-off-by: Andreas Gruenbacher <agruen@use.de>
Cc: Mike Halcrow <mhalcrow@us.ibm.com>
Cc: Phillip Hellewell <phillip@hellewell.homeip.net>
---
fs/ecryptfs/dentry.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -51,13 +51,17 @@ static int ecryptfs_d_revalidate(struct
if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
goto out;
- dentry_save = nd->dentry;
- vfsmount_save = nd->mnt;
- nd->dentry = lower_dentry;
- nd->mnt = lower_mnt;
+ if (nd) {
+ dentry_save = nd->dentry;
+ vfsmount_save = nd->mnt;
+ nd->dentry = lower_dentry;
+ nd->mnt = lower_mnt;
+ }
rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd);
- nd->dentry = dentry_save;
- nd->mnt = vfsmount_save;
+ if (nd) {
+ nd->dentry = dentry_save;
+ nd->mnt = vfsmount_save;
+ }
if (dentry->d_inode) {
struct inode *lower_inode =
ecryptfs_inode_to_lower(dentry->d_inode);

View file

@ -1,173 +0,0 @@
Allow the dfa to return its state, which will allow for pair matches.
---
security/apparmor/apparmor.h | 7 ++-
security/apparmor/inline.h | 2
security/apparmor/match.c | 99 ++++++++++++++++++++++++++++++++++++++-----
security/apparmor/match.h | 2
4 files changed, 99 insertions(+), 11 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -45,7 +45,6 @@
#define AA_SECURE_EXEC_NEEDED 1
-
/* Control parameters (0 or 1), settable thru module/boot flags or
* via /sys/kernel/security/apparmor/control */
extern int apparmor_complain;
@@ -260,5 +259,11 @@ extern void aa_match_free(struct aa_dfa
extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
extern int verify_dfa(struct aa_dfa *dfa);
extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str);
+extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
+ const char *str);
+extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
+ const char *str, unsigned int *final);
+extern unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
+ unsigned int start);
#endif /* __APPARMOR_H */
--- a/security/apparmor/inline.h
+++ b/security/apparmor/inline.h
@@ -12,6 +12,8 @@
#include <linux/sched.h>
+#include "match.h"
+
static inline int mediated_filesystem(struct inode *inode)
{
return !(inode->i_sb->s_flags & MS_NOUSER);
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -208,22 +208,26 @@ void aa_match_free(struct aa_dfa *dfa)
}
/**
- * aa_dfa_match - match @path against @dfa starting in @state
- * @dfa: the dfa to match @path against
- * @state: the state to start matching in
- * @path: the path to match against the dfa
+ * aa_dfa_next_state - traverse @dfa to find state @str stops at
+ * @dfa: the dfa to match @str against
+ * @start: the state of the dfa to start matching in
+ * @str: the string to match against the dfa
*
- * aa_dfa_match will match the full path length and return the state it
- * finished matching in. The final state is used to look up the accepting
- * label.
+ * aa_dfa_next_state will match @str against the dfa and return the state it
+ * finished matching in. The final state can be used to look up the accepting
+ * label, or as the start state of a continuing match.
*/
-unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str)
+unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
+ const char *str)
{
u16 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
u16 *next = NEXT_TABLE(dfa);
u16 *check = CHECK_TABLE(dfa);
- unsigned int state = 1, pos;
+ unsigned int state = start, pos;
+
+ if (state == 0)
+ return 0;
/* current state is <state>, matching character *str */
if (dfa->tables[YYTD_ID_EC - 1]) {
@@ -244,5 +248,80 @@ unsigned int aa_dfa_match(struct aa_dfa
state = def[state];
}
}
- return ACCEPT_TABLE(dfa)[state];
+ return state;
+}
+
+/**
+ * aa_dfa_null_transition - step to next state after null character
+ * @dfa: the dfa to match against
+ * @start: the state of the dfa to start matching in
+ *
+ * aa_dfa_null_transition transitions to the next state after a null
+ * character which is not used in standard matching and is only
+ * used to seperate pairs.
+ */
+unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
+{
+ u16 *def = DEFAULT_TABLE(dfa);
+ u32 *base = BASE_TABLE(dfa);
+ u16 *next = NEXT_TABLE(dfa);
+ u16 *check = CHECK_TABLE(dfa);
+ unsigned int state = start, pos;
+
+ /* current state is <state>, matching character *str */
+ if (dfa->tables[YYTD_ID_EC - 1]) {
+ u8 *equiv = EQUIV_TABLE(dfa);
+ pos = base[state] + equiv[0];
+ if (check[pos] == state)
+ state = next[pos];
+ else
+ state = def[state];
+ } else {
+ pos = base[state] + 0;
+ if (check[pos] == state)
+ state = next[pos];
+ else
+ state = def[state];
+ }
+
+ return state;
+}
+
+/**
+ * aa_dfa_match - find accept perm for @str in @dfa
+ * @dfa: the dfa to match @str against
+ * @str: the string to match against the dfa
+ *
+ * aa_dfa_match will match @str and return the accept perms for the
+ * final state.
+ */
+unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str)
+{
+ return ACCEPT_TABLE(dfa)[aa_dfa_next_state(dfa, DFA_START, str)];
}
+
+/**
+ * aa_match_state - find accept perm and state for @str in @dfa
+ * @dfa: the dfa to match @str against
+ * @start: the state to start the match from
+ * @str: the string to match against the dfa
+ * @final: the state that the match finished in
+ *
+ * aa_match_state will match @str and return the accept perms, and @final
+ * state, the match occured in.
+ */
+unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
+ const char *str, unsigned int *final)
+{
+ unsigned int state;
+ if (dfa) {
+ state = aa_dfa_next_state(dfa, start, str);
+ if (final)
+ *final = state;
+ return ACCEPT_TABLE(dfa)[state];
+ }
+ if (final)
+ *final = 0;
+ return 0;
+}
+
--- a/security/apparmor/match.h
+++ b/security/apparmor/match.h
@@ -12,6 +12,8 @@
#ifndef __MATCH_H
#define __MATCH_H
+#define DFA_START 1
+
/**
* The format used for transition tables is based on the GNU flex table
* file format (--tables-file option; see Table File Format in the flex

View file

@ -1,72 +0,0 @@
---
security/apparmor/apparmor.h | 43 ++++++++++++++++++++++++++++---------------
1 file changed, 28 insertions(+), 15 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -26,25 +26,33 @@
#define AA_MAY_LINK 0x0010
#define AA_MAY_LOCK 0x0020
#define AA_EXEC_MMAP 0x0040
-#define AA_EXEC_UNSAFE 0x0080
-#define AA_EXEC_MOD_0 0x0100
-#define AA_EXEC_MOD_1 0x0200
+#define AA_MAY_MOUNT 0x0080 /* no direct audit mapping */
+#define AA_EXEC_UNSAFE 0x0100
+#define AA_EXEC_MOD_0 0x0200
+#define AA_EXEC_MOD_1 0x0400
+#define AA_EXEC_MOD_2 0x0800
+#define AA_EXEC_MOD_3 0x1000
+#define AA_EXEC_MOD_4 0x2000
+
#define AA_BASE_PERMS (MAY_READ | MAY_WRITE | MAY_EXEC | \
MAY_APPEND | AA_MAY_LINK | \
AA_MAY_LOCK | AA_EXEC_MMAP | \
- AA_EXEC_UNSAFE | AA_EXEC_MOD_0 | \
- AA_EXEC_MOD_1)
-#define AA_LINK_SUBSET_TEST 0x0020
-
-#define AA_EXEC_UNCONFINED 0
-#define AA_EXEC_INHERIT AA_EXEC_MOD_0
-#define AA_EXEC_PROFILE AA_EXEC_MOD_1
-#define AA_EXEC_PIX (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
-
-#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
+ AA_MAY_MOUNT | AA_EXEC_UNSAFE | \
+ AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
+ AA_EXEC_MOD_2 | AA_EXEC_MOD_3 | \
+ AA_EXEC_MOD_4)
+
+#define AA_EXEC_UNCONFINED AA_EXEC_MOD_0
+#define AA_EXEC_INHERIT AA_EXEC_MOD_1
+#define AA_EXEC_PROFILE (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
+#define AA_EXEC_PIX AA_EXEC_MOD_2
+
+#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
+ AA_EXEC_MOD_2 | AA_EXEC_MOD_3 | \
+ AA_EXEC_MOD_4)
#define AA_USER_SHIFT 0
-#define AA_OTHER_SHIFT 10
+#define AA_OTHER_SHIFT 14
#define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT)
#define AA_OTHER_PERMS (AA_BASE_PERMS << AA_OTHER_SHIFT)
@@ -68,11 +76,16 @@
#define AA_ALL_EXEC_MODS (AA_USER_EXEC_MODS | \
AA_OTHER_EXEC_MODS)
+/* overloaded permissions for link pairs */
+#define AA_LINK_SUBSET_TEST 0x0020
+
/* shared permissions that are not duplicated in user::other */
+#define AA_AUDIT_FIELD 0x10000000
#define AA_CHANGE_HAT 0x20000000
#define AA_CHANGE_PROFILE 0x40000000
-#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
+#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE | \
+ AA_AUDIT_FIELD)
#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_SHARED_PERMS)

View file

@ -1,130 +0,0 @@
From: Miklos Szeredi <mszeredi@suse.cz>
Add a new file operation: f_op->fgetattr(), that is invoked by
fstat(). Fall back to i_op->getattr() if it is not defined.
We need this because fstat() semantics can in some cases be better
implemented if the filesystem has the open file available.
Let's take the following example: we have a network filesystem, with
the server implemented as an unprivileged userspace process running on
a UNIX system (this is basically what sshfs does).
We want the filesystem to follow the familiar UNIX file semantics as
closely as possible. If for example we have this sequence of events,
we still would like fstat to work correctly:
1) file X is opened on client
2) file X is renamed to Y on server
3) fstat() is performed on open file descriptor on client
This is only possible if the filesystem server acutally uses fstat()
on a file descriptor obtained when the file was opened. Which means,
the filesystem client needs a way to get this information from the
VFS.
Even if we assume, that the remote filesystem never changes, it is
difficult to implement open-unlink-fstat semantics correctly in the
client, without having this information.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
---
fs/fuse/file.c | 13 +++++++++++++
fs/stat.c | 29 ++++++++++++++++++++++++++++-
include/linux/fs.h | 1 +
3 files changed, 42 insertions(+), 1 deletion(-)
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -871,6 +871,17 @@ static int fuse_file_flock(struct file *
return err;
}
+static int fuse_file_fgetattr(struct file *file, struct kstat *stat)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+
+ if (!fuse_allow_task(fc, current))
+ return -EACCES;
+
+ return fuse_update_attributes(inode, stat, file, NULL);
+}
+
static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
{
struct inode *inode = mapping->host;
@@ -920,6 +931,7 @@ static const struct file_operations fuse
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
+ .fgetattr = fuse_file_fgetattr,
.splice_read = generic_file_splice_read,
};
@@ -933,6 +945,7 @@ static const struct file_operations fuse
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
+ .fgetattr = fuse_file_fgetattr,
/* no mmap and splice_read */
};
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -55,6 +55,33 @@ int vfs_getattr(struct vfsmount *mnt, st
EXPORT_SYMBOL(vfs_getattr);
+/*
+ * Perform getattr on an open file
+ *
+ * Fall back to i_op->getattr (or generic_fillattr) if the filesystem
+ * doesn't define an f_op->fgetattr operation.
+ */
+static int vfs_fgetattr(struct file *file, struct kstat *stat)
+{
+ struct vfsmount *mnt = file->f_path.mnt;
+ struct dentry *dentry = file->f_path.dentry;
+ struct inode *inode = dentry->d_inode;
+ int retval;
+
+ retval = security_inode_getattr(mnt, dentry);
+ if (retval)
+ return retval;
+
+ if (file->f_op && file->f_op->fgetattr) {
+ return file->f_op->fgetattr(file, stat);
+ } else if (inode->i_op->getattr) {
+ return inode->i_op->getattr(mnt, dentry, stat);
+ } else {
+ generic_fillattr(inode, stat);
+ return 0;
+ }
+}
+
int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
{
struct nameidata nd;
@@ -101,7 +128,7 @@ int vfs_fstat(unsigned int fd, struct ks
int error = -EBADF;
if (f) {
- error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
+ error = vfs_fgetattr(f, stat);
fput(f);
}
return error;
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1188,6 +1188,7 @@ struct file_operations {
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
+ int (*fgetattr)(struct file *, struct kstat *);
};
struct inode_operations {

View file

@ -12,12 +12,12 @@ Cc: Miklos Szeredi <mszeredi@suse.cz>
---
fs/nfsd/vfs.c | 12 +++++++-----
fs/open.c | 4 +++-
2 files changed, 10 insertions(+), 6 deletions(-)
fs/open.c | 5 ++++-
2 files changed, 11 insertions(+), 6 deletions(-)
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -413,7 +413,7 @@ static ssize_t nfsd_getxattr(struct dent
@@ -412,7 +412,7 @@ static ssize_t nfsd_getxattr(struct dent
{
ssize_t buflen;
@ -26,7 +26,7 @@ Cc: Miklos Szeredi <mszeredi@suse.cz>
if (buflen <= 0)
return buflen;
@@ -421,7 +421,7 @@ static ssize_t nfsd_getxattr(struct dent
@@ -420,7 +420,7 @@ static ssize_t nfsd_getxattr(struct dent
if (!*buf)
return -ENOMEM;
@ -35,7 +35,7 @@ Cc: Miklos Szeredi <mszeredi@suse.cz>
}
#endif
@@ -447,7 +447,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
@@ -446,7 +446,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
goto out;
}
@ -44,9 +44,9 @@ Cc: Miklos Szeredi <mszeredi@suse.cz>
out:
kfree(buf);
return error;
@@ -2051,12 +2051,14 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
mnt = fhp->fh_export->ex_mnt;
@@ -2111,12 +2111,14 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
if (error)
goto getout;
if (size)
- error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size,0);
+ error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
@ -63,7 +63,7 @@ Cc: Miklos Szeredi <mszeredi@suse.cz>
}
--- a/fs/open.c
+++ b/fs/open.c
@@ -581,7 +581,7 @@ asmlinkage long sys_fchmod(unsigned int
@@ -589,7 +589,7 @@ asmlinkage long sys_fchmod(unsigned int
if (mode == (mode_t) -1)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
@ -72,12 +72,13 @@ Cc: Miklos Szeredi <mszeredi@suse.cz>
err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);
@@ -661,6 +661,8 @@ static int chown_common(struct dentry *
@@ -670,6 +670,9 @@ static int chown_common(struct dentry *
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+ if (file)
+ newattrs.ia_valid |= ATTR_FILE;
+
mutex_lock(&inode->i_mutex);
error = fnotify_change(dentry, mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);

View file

@ -9,23 +9,22 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
fs/namei.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -313,7 +313,13 @@ int vfs_permission(struct nameidata *nd,
@@ -318,7 +318,12 @@ int vfs_permission(struct nameidata *nd,
*/
int file_permission(struct file *file, int mask)
{
- return permission(file->f_path.dentry->d_inode, mask, NULL);
+ struct nameidata nd;
+
+ nd.dentry = file->f_path.dentry;
+ nd.mnt = file->f_path.mnt;
+ nd.path = file->f_path;
+ nd.flags = LOOKUP_ACCESS;
+
+ return permission(nd.dentry->d_inode, mask, &nd);
+ return permission(nd.path.dentry->d_inode, mask, &nd);
}
/*

View file

@ -1,17 +0,0 @@
---
security/apparmor/main.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -1239,9 +1239,7 @@ repeat:
return -ENOENT;
}
- if (PROFILE_COMPLAIN(profile) ||
- (ns == profile->ns &&
- (aa_match(profile->file_rules, name) & AA_CHANGE_PROFILE)))
+ if (PROFILE_COMPLAIN(profile))
error = do_change_profile(profile, ns, name, 0, 0, &sa);
else {
/* check for a rule with a namespace prepended */

View file

@ -1,68 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Distinguish between connected and disconnected paths in d_path()
Change d_path() so that it will never return a path starting with '/' if
the path doesn't lead up to the chroot directory. Also ensure that the
path returned never is the empty string: this would only occur with a lazily unmounted file system; return "." in that case instead.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/dcache.c | 18 ++++--------------
fs/namespace.c | 3 ---
2 files changed, 4 insertions(+), 17 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1829,8 +1829,11 @@ global_root:
buffer++;
buflen++;
}
- if (is_slash)
+ if (is_slash) {
+ if (*buffer == '\0')
+ *--buffer = '.';
goto out;
+ }
}
if (buflen < namelen)
goto Elong;
@@ -1843,18 +1846,6 @@ Elong:
goto out;
}
-static char *__connect_d_path(char *path, char *buffer)
-{
- if (!IS_ERR(path) && *path != '/') {
- /* Pretend that disconnected paths are hanging off the root. */
- if (path == buffer)
- path = ERR_PTR(-ENAMETOOLONG);
- else
- *--path = '/';
- }
- return path;
-}
-
/* write full pathname into buffer and return start of pathname */
char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
int buflen)
@@ -1868,7 +1859,6 @@ char *d_path(struct dentry *dentry, stru
root = dget(current->fs->root);
read_unlock(&current->fs->lock);
res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
- res = __connect_d_path(res, buf);
dput(root);
mntput(rootmnt);
return res;
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1917,9 +1917,6 @@ char *d_namespace_path(struct dentry *de
res = __d_path(dentry, vfsmnt, root, nsrootmnt, buf, buflen, 1);
dput(root);
mntput(nsrootmnt);
- /* Prevent empty path for lazily unmounted filesystems. */
- if (!IS_ERR(res) && *res == '\0')
- *--res = '.';
return res;
}
EXPORT_SYMBOL(d_namespace_path);

View file

@ -1,134 +0,0 @@
---
security/apparmor/match.c | 74 +++++++++++++++++++++++++++++++---------------
1 file changed, 51 insertions(+), 23 deletions(-)
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -213,17 +213,23 @@ void aa_match_free(struct aa_dfa *dfa)
}
/**
- * aa_dfa_next_state - traverse @dfa to find state @str stops at
+ * aa_dfa_next_state_len - traverse @dfa to find state @str stops at
* @dfa: the dfa to match @str against
* @start: the state of the dfa to start matching in
- * @str: the string to match against the dfa
+ * @str: the string of bytes to match against the dfa
+ * @len: length of the string of bytes to match
*
* aa_dfa_next_state will match @str against the dfa and return the state it
* finished matching in. The final state can be used to look up the accepting
* label, or as the start state of a continuing match.
+ *
+ * aa_dfa_next_state could be implement using this function by doing
+ * return aa_dfa_next_state_len(dfa, start, str, strlen(str));
+ * but that would require traversing the string twice and be slightly
+ * slower.
*/
-unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
- const char *str)
+unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start,
+ const char *str, int len)
{
u16 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
@@ -237,7 +243,7 @@ unsigned int aa_dfa_next_state(struct aa
/* current state is <state>, matching character *str */
if (dfa->tables[YYTD_ID_EC - 1]) {
u8 *equiv = EQUIV_TABLE(dfa);
- while (*str) {
+ for (; len; len--) {
pos = base[state] + equiv[(u8)*str++];
if (check[pos] == state)
state = next[pos];
@@ -245,7 +251,7 @@ unsigned int aa_dfa_next_state(struct aa
state = def[state];
}
} else {
- while (*str) {
+ for (; len; len--) {
pos = base[state] + (u8)*str++;
if (check[pos] == state)
state = next[pos];
@@ -257,15 +263,17 @@ unsigned int aa_dfa_next_state(struct aa
}
/**
- * aa_dfa_null_transition - step to next state after null character
- * @dfa: the dfa to match against
+ * aa_dfa_next_state - traverse @dfa to find state @str stops at
+ * @dfa: the dfa to match @str against
* @start: the state of the dfa to start matching in
+ * @str: the null terminated string of bytes to match against the dfa
*
- * aa_dfa_null_transition transitions to the next state after a null
- * character which is not used in standard matching and is only
- * used to seperate pairs.
+ * aa_dfa_next_state will match @str against the dfa and return the state it
+ * finished matching in. The final state can be used to look up the accepting
+ * label, or as the start state of a continuing match.
*/
-unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
+unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
+ const char *str)
{
u16 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
@@ -273,26 +281,46 @@ unsigned int aa_dfa_null_transition(stru
u16 *check = CHECK_TABLE(dfa);
unsigned int state = start, pos;
+ if (state == 0)
+ return 0;
+
/* current state is <state>, matching character *str */
if (dfa->tables[YYTD_ID_EC - 1]) {
u8 *equiv = EQUIV_TABLE(dfa);
- pos = base[state] + equiv[0];
- if (check[pos] == state)
- state = next[pos];
- else
- state = def[state];
+ while (*str) {
+ pos = base[state] + equiv[(u8)*str++];
+ if (check[pos] == state)
+ state = next[pos];
+ else
+ state = def[state];
+ }
} else {
- pos = base[state] + 0;
- if (check[pos] == state)
- state = next[pos];
- else
- state = def[state];
+ while (*str) {
+ pos = base[state] + (u8)*str++;
+ if (check[pos] == state)
+ state = next[pos];
+ else
+ state = def[state];
+ }
}
-
return state;
}
/**
+ * aa_dfa_null_transition - step to next state after null character
+ * @dfa: the dfa to match against
+ * @start: the state of the dfa to start matching in
+ *
+ * aa_dfa_null_transition transitions to the next state after a null
+ * character which is not used in standard matching and is only
+ * used to seperate pairs.
+ */
+unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
+{
+ return aa_dfa_next_state_len(dfa, start, "", 1);
+}
+
+/**
* aa_dfa_match - find accept perm for @str in @dfa
* @dfa: the dfa to match @str against
* @str: the string to match against the dfa

View file

@ -1,37 +0,0 @@
---
fs/fuse/dir.c | 2 +-
fs/fuse/file.c | 2 +-
fs/fuse/fuse_i.h | 3 +++
3 files changed, 5 insertions(+), 2 deletions(-)
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1167,7 +1167,7 @@ static int fuse_setattr(struct dentry *e
return fuse_do_setattr(entry, attr, NULL);
}
-static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
+int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
struct kstat *stat)
{
struct inode *inode = entry->d_inode;
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -855,7 +855,7 @@ static int fuse_file_fgetattr(struct fil
if (!fuse_allow_task(fc, current))
return -EACCES;
- return fuse_update_attributes(inode, stat, file, NULL);
+ return fuse_getattr(file->f_vfsmnt, file->f_dentry, stat);
}
static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -597,3 +597,6 @@ int fuse_valid_type(int m);
int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task);
u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id);
+
+int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
+ struct kstat *stat);

View file

@ -1,30 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Make getcwd() only return valid paths
Make getcwd() fail with -ENOENT if the current working directory is
disconnected: the process is not asking for some previous name of that
directory but for the current name; returning a path meaningless in the
context of that process makes no sense.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/dcache.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1910,10 +1910,12 @@ asmlinkage long sys_getcwd(char __user *
read_unlock(&current->fs->lock);
cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
- cwd = __connect_d_path(cwd, page);
error = PTR_ERR(cwd);
if (IS_ERR(cwd))
goto out;
+ error = -ENOENT;
+ if (*cwd != '/')
+ goto out;
error = -ERANGE;
len = PAGE_SIZE + page - cwd;

View file

@ -1,76 +0,0 @@
---
security/apparmor/main.c | 37 ++++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 17 deletions(-)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -68,7 +68,7 @@ static int aa_link_denied(struct aa_prof
int *request_mask)
{
unsigned int state;
- int l_mode, t_mode, denied_mask = 0;
+ int l_mode, t_mode, l_subset, denied_mask = 0;
int link_mask = AA_MAY_LINK << target_mode;
*request_mask = link_mask;
@@ -83,31 +83,35 @@ static int aa_link_denied(struct aa_prof
if (!(mode & link_mask))
denied_mask |= link_mask;
+ /* return if link subset test is not required */
if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
return denied_mask;
}
- /* do link perm subset test */
- t_mode = aa_match(profile->file_rules, target);
-
- /* Ignore valid-profile-transition flags. */
- l_mode &= ~AA_SHARED_PERMS;
- t_mode &= ~AA_SHARED_PERMS;
-
- *request_mask = l_mode | link_mask;
-
- /* Link always requires 'l' on the link for both parts of the pair.
+ /* Do link perm subset test
* If a subset test is required a permission subset test of the
* perms for the link are done against the user:group:other of the
* target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
*
* If the link has 'x', an exact match of all the execute flags
- * ('i', 'u', 'p'). safe exec is treated as a subset of unsafe exec
+ * must match.
*/
-#define SUBSET_PERMS (AA_FILE_PERMS & ~AA_LINK_BITS)
denied_mask |= ~l_mode & link_mask;
- if (l_mode & SUBSET_PERMS) {
- denied_mask |= (l_mode & SUBSET_PERMS) & ~t_mode;
+
+ t_mode = aa_match(profile->file_rules, target);
+
+
+ /* For actual subset test ignore valid-profile-transition flags,
+ * and link bits
+ */
+ l_mode &= ~(AA_SHARED_PERMS | AA_LINK_BITS);
+ t_mode &= ~(AA_SHARED_PERMS | AA_LINK_BITS);
+ l_subset = l_mode & AA_FILE_PERMS;
+
+ *request_mask = l_mode | link_mask;
+
+ if (l_subset) {
+ denied_mask |= (l_subset) & ~t_mode;
if (denied_mask & AA_EXEC_BITS)
denied_mask |= l_mode & AA_ALL_EXEC_MODS;
else if (l_mode & AA_EXEC_BITS) {
@@ -126,9 +130,8 @@ static int aa_link_denied(struct aa_prof
denied_mask |= AA_OTHER_EXEC |
(l_mode & AA_OTHER_EXEC_MODS);
}
- } else
+ } else if (t_mode & AA_FILE_PERMS)
denied_mask |= t_mode | link_mask;
-#undef SUBSET_PERMS
return denied_mask;
}

View file

@ -1,22 +0,0 @@
fix bug where the error code and mask are not being set correctly
when pathname lookup fails.
---
security/apparmor/main.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -191,8 +191,10 @@ static int aa_perm_dentry(struct aa_prof
*/
if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
sa->denied_mask = 0;
- else
- sa->denied_mask = PTR_ERR(sa->name);
+ else {
+ sa->denied_mask = sa->requested_mask;
+ sa->error_code = PTR_ERR(sa->name);
+ }
sa->name = NULL;
} else
sa->denied_mask = aa_file_denied(profile, sa->name,

View file

@ -1,26 +0,0 @@
---
security/apparmor/main.c | 2 +-
security/apparmor/module_interface.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -1119,7 +1119,7 @@ aa_x_to_profile(struct aa_profile *profi
default:
/* all other indexes are named transitions */
index = AA_EXEC_INDEX(xmode);
- if (index - 4 > profile->exec_table_size) {
+ if (index - 4 >= profile->exec_table_size) {
sa->info = "invalid named transition - exec failed";
sa->error_code = -EACCES;
new_profile = ERR_PTR(-EACCES);
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -319,6 +319,7 @@ static int aa_unpack_exec_table(struct a
goto fail;
if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
goto fail;
+ profile->exec_table_size = size;
}
return 1;

View file

@ -1,38 +0,0 @@
---
security/apparmor/lsm.c | 18 ------------------
1 file changed, 18 deletions(-)
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -717,22 +717,6 @@ static int apparmor_socket_shutdown(stru
return aa_revalidate_sk(sk, "socket_shutdown");
}
-static int apparmor_socket_getpeersec_stream(struct socket *sock,
- char __user *optval, int __user *optlen, unsigned len)
-{
- struct sock *sk = sock->sk;
-
- return aa_revalidate_sk(sk, "socket_getpeersec_stream");
-}
-
-static int apparmor_socket_getpeersec_dgram(struct socket *sock,
- struct sk_buff *skb, u32 *secid)
-{
- struct sock *sk = sock->sk;
-
- return aa_revalidate_sk(sk, "socket_getpeersec_dgram");
-}
-
static int apparmor_getprocattr(struct task_struct *task, char *name,
char **value)
{
@@ -882,8 +866,6 @@ struct security_operations apparmor_ops
.socket_getsockopt = apparmor_socket_getsockopt,
.socket_setsockopt = apparmor_socket_setsockopt,
.socket_shutdown = apparmor_socket_shutdown,
- .socket_getpeersec_stream = apparmor_socket_getpeersec_stream,
- .socket_getpeersec_dgram = apparmor_socket_getpeersec_dgram,
};
static void info_message(const char *str)

View file

@ -1,92 +0,0 @@
---
security/apparmor/list.c | 2 +-
security/apparmor/main.c | 20 +++++++++++---------
security/apparmor/procattr.c | 13 +++++++------
3 files changed, 19 insertions(+), 16 deletions(-)
--- a/security/apparmor/list.c
+++ b/security/apparmor/list.c
@@ -142,7 +142,7 @@ static int seq_show_profile(struct seq_f
seq_printf(f, "%s (%s)\n", profile->name,
PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
else
- seq_printf(f, "%s:%s (%s)\n", profile->ns->name, profile->name,
+ seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name,
PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
return 0;
}
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -251,8 +251,10 @@ static int aa_audit_base(struct aa_profi
audit_log_format(ab, " profile=");
audit_log_untrustedstring(ab, profile->name);
- audit_log_format(ab, " namespace=");
- audit_log_untrustedstring(ab, profile->ns->name);
+ if (profile->ns != default_namespace) {
+ audit_log_format(ab, " namespace=");
+ audit_log_untrustedstring(ab, profile->ns->name);
+ }
}
audit_log_end(ab);
@@ -1364,15 +1366,15 @@ repeat:
if (hat_name) {
char *name, *profile_name;
- /* Not Yet. This perm check is currently done by searching
- for the hat profile. When hat style profile names
- become more generic then this will be needed.
- if (!(aa_match(profile->file_rules, hat_name) &
- AA_CHANGE_PROFILE)) {
- error = -EACCES;
+ if (!PROFILE_COMPLAIN(profile) &&
+ !(aa_match(profile->file_rules, hat_name, NULL)
+ & AA_CHANGE_HAT)) {
+ /* missing permission to change_hat is treated the
+ * same as a failed hat search */
+ error = -ENOENT;
goto out;
}
- */
+
if (previous_profile)
profile_name = previous_profile->name;
else
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -24,15 +24,16 @@ int aa_getprocattr(struct aa_profile *pr
mode_len = strlen(mode_str);
name_len = strlen(profile->name);
if (profile->ns != default_namespace)
- ns_len = strlen(profile->ns->name) + 1;
+ ns_len = strlen(profile->ns->name) + 2;
*len = mode_len + ns_len + name_len + 1;
str = kmalloc(*len, GFP_ATOMIC);
if (!str)
return -ENOMEM;
if (ns_len) {
- memcpy(str, profile->ns->name, ns_len - 1);
- str += ns_len - 1;
+ *str++ = ':';
+ memcpy(str, profile->ns->name, ns_len - 2);
+ str += ns_len - 2;
*str++ = ':';
}
memcpy(str, profile->name, name_len);
@@ -96,11 +97,11 @@ int aa_setprocattr_changeprofile(char *a
{
char *name = args, *ns_name = NULL;
- if (name[0] != '/') {
- char *split = strchr(name, ':');
+ if (name[0] == ':') {
+ char *split = strchr(&name[1], ':');
if (split) {
*split = 0;
- ns_name = name;
+ ns_name = &name[1];
name = split + 1;
}
}

View file

@ -1,18 +0,0 @@
The old style of casting in the rcu_dereference fails to compile with
the newer rcu_dereference macro.
---
security/apparmor/inline.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/security/apparmor/inline.h
+++ b/security/apparmor/inline.h
@@ -19,7 +19,7 @@ static inline int mediated_filesystem(st
static inline struct aa_task_context *aa_task_context(struct task_struct *task)
{
- return rcu_dereference((struct aa_task_context *)task->security);
+ return (struct aa_task_context *) rcu_dereference(task->security);
}
/**

View file

@ -1,15 +0,0 @@
---
security/apparmor/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -338,7 +338,7 @@ static void aa_audit_file_mask(struct au
aa_audit_file_sub_mask(ab, other,
(mask & AA_OTHER_PERMS) >> AA_OTHER_SHIFT);
- audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
+ audit_log_format(ab, " %s=\"%s:%s\"", name, user, other);
}
static const char *address_families[] = {

View file

@ -15,7 +15,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2097,6 +2097,10 @@ int vfs_rmdir(struct inode *dir, struct
@@ -2232,6 +2232,10 @@ int vfs_rmdir(struct inode *dir, struct
if (!dir->i_op || !dir->i_op->rmdir)
return -EPERM;
@ -26,7 +26,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
DQUOT_INIT(dir);
mutex_lock(&dentry->d_inode->i_mutex);
@@ -2104,12 +2108,9 @@ int vfs_rmdir(struct inode *dir, struct
@@ -2239,12 +2243,9 @@ int vfs_rmdir(struct inode *dir, struct
if (d_mountpoint(dentry))
error = -EBUSY;
else {

View file

@ -1,278 +0,0 @@
---
security/Makefile | 2
security/foobar/Makefile | 1
security/foobar/foobar.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 260 insertions(+)
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,3 +16,5 @@ obj-$(CONFIG_SECURITY) += security.o d
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
+
+subdir-$(CONFIG_SECURITY) += foobar
--- /dev/null
+++ b/security/foobar/Makefile
@@ -0,0 +1 @@
+obj-m += foobar.o
--- /dev/null
+++ b/security/foobar/foobar.c
@@ -0,0 +1,257 @@
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/namei.h>
+
+#define log_path(dentry, mnt, fmt...) \
+ __log_path(__FUNCTION__, dentry, mnt, NULL, ##fmt)
+
+#define log_path_inode(inode, fmt...) \
+ __log_path(__FUNCTION__, NULL, NULL, inode, ##fmt)
+
+static int show_traversals;
+module_param(show_traversals, bool, 0644);
+
+static void __log_path(const char *op, struct dentry *dentry,
+ struct vfsmount *mnt, struct inode *inode,
+ char *fmt, ...)
+{
+ va_list ap;
+ char *page = NULL, *name = "<?>";
+
+ page = (char *)__get_free_page(GFP_KERNEL);
+ if (!page)
+ name = "<ENOMEM>";
+ else if (mnt) {
+ name = d_path(dentry, mnt, page + 1, PAGE_SIZE - 2);
+ if (IS_ERR(name)) {
+ snprintf(page, PAGE_SIZE, "<%ld>", PTR_ERR(name));
+ name = page;
+ } else {
+ page[PAGE_SIZE - 2] = '"';
+ page[PAGE_SIZE - 1] = '\0';
+ *--name = '"';
+ }
+ } else if (dentry) {
+ snprintf(page, PAGE_SIZE, "<%s>", dentry->d_name.name);
+ name = page;
+ } else if (inode) {
+ snprintf(page, PAGE_SIZE, "<%s:%ld>",
+ inode->i_sb->s_type->name,
+ inode->i_ino);
+ name = page;
+ }
+
+ if (fmt) {
+ char *buffer = (char *)__get_free_page(GFP_KERNEL);
+
+ if (buffer) {
+ int n;
+
+ n = snprintf(buffer, PAGE_SIZE, KERN_INFO "%s(%s, ",
+ op, name);
+ va_start(ap, fmt);
+ n += vsnprintf(buffer + n, PAGE_SIZE - n, fmt, ap);
+ va_end(ap);
+ snprintf(buffer + n, PAGE_SIZE - n, ")\n");
+ printk("%s", buffer);
+
+ free_page((unsigned long)buffer);
+ } else
+ printk("%s: Out of memory\n", __FUNCTION__);
+ } else
+ printk(KERN_INFO "%s(%s)\n", op, name);
+
+ free_page((unsigned long)page);
+}
+
+static int foobar_inode_mkdir(struct inode *inode, struct dentry *dentry,
+ struct vfsmount *mnt, int mask)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_rmdir(struct inode *inode, struct dentry *dentry,
+ struct vfsmount *mnt)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_create(struct inode *inode, struct dentry *dentry,
+ struct vfsmount *mnt, int mask)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_link(struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
+ struct inode *inode,
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
+{
+ log_path(old_dentry, old_mnt, "<old>");
+ log_path(new_dentry, new_mnt, "<new>");
+
+ return 0;
+}
+
+static int foobar_inode_unlink(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_mknod(struct inode *inode, struct dentry *dentry,
+ struct vfsmount *mnt, int mode, dev_t dev)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_rename(struct inode *old_inode,
+ struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
+ struct inode *new_inode,
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
+{
+ log_path(old_dentry, old_mnt, "<old>");
+ log_path(new_dentry, new_mnt, "<new>");
+
+ return 0;
+}
+
+static int foobar_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *iattr)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags, struct file *file)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_getxattr(struct dentry *dentry,
+ struct vfsmount *mnt, char *name, struct file *file)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_listxattr(struct dentry *dentry,
+ struct vfsmount *mnt, struct file *file)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_removexattr(struct dentry *dentry,
+ struct vfsmount *mnt, char *name, struct file *file)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_symlink(struct inode *dir,
+ struct dentry *dentry, struct vfsmount *mnt,
+ const char *old_name)
+{
+ log_path(dentry, mnt, NULL);
+
+ return 0;
+}
+
+static int foobar_inode_permission(struct inode *inode, int mask,
+ struct nameidata *nd)
+{
+ if (nd && (nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE)) &&
+ !show_traversals)
+ return 0;
+
+ if (nd) {
+ char *parent = "", *sep="", *cont = "";
+
+ if (nd->flags & LOOKUP_PARENT)
+ parent = "LOOKUP_PARENT";
+ if (nd->flags & LOOKUP_CONTINUE)
+ cont = "LOOKUP_CONTINUE";
+ if ((nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE)) ==
+ (LOOKUP_PARENT | LOOKUP_CONTINUE))
+ sep = ", ";
+ else if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE)))
+ sep = "0";
+
+ log_path(nd->dentry, nd->mnt, "%c%c%c%c, %s%s%s",
+ mask & MAY_READ ? 'r' : '-',
+ mask & MAY_WRITE ? 'w' : '-',
+ mask & MAY_EXEC ? 'x' : '-',
+ mask & MAY_APPEND ? 'a' : '-',
+ parent, sep, cont);
+ } else {
+ log_path_inode(inode, "%c%c%c%c, 0",
+ mask & MAY_READ ? 'r' : '-',
+ mask & MAY_WRITE ? 'w' : '-',
+ mask & MAY_EXEC ? 'x' : '-',
+ mask & MAY_APPEND ? 'a' : '-');
+ }
+
+ return 0;
+}
+
+struct security_operations foobar_ops = {
+ .inode_create = foobar_inode_create,
+ .inode_link = foobar_inode_link,
+ .inode_unlink = foobar_inode_unlink,
+ .inode_mkdir = foobar_inode_mkdir,
+ .inode_rmdir = foobar_inode_rmdir,
+ .inode_mknod = foobar_inode_mknod,
+ .inode_rename = foobar_inode_rename,
+ .inode_setattr = foobar_inode_setattr,
+ .inode_setxattr = foobar_inode_setxattr,
+ .inode_getxattr = foobar_inode_getxattr,
+ .inode_listxattr = foobar_inode_listxattr,
+ .inode_removexattr = foobar_inode_removexattr,
+ .inode_symlink = foobar_inode_symlink,
+ .inode_permission = foobar_inode_permission,
+};
+
+static int __init foobar_init(void)
+{
+ int error;
+
+ error = register_security(&foobar_ops);
+ if (error)
+ printk(KERN_ERR "Unable to load foobar lsm\n");
+
+ return error;
+}
+
+static void __exit foobar_exit(void)
+{
+ if (unregister_security(&foobar_ops))
+ printk(KERN_ERR "Unable to properly unregister foobar lsm\n");
+}
+
+module_init(foobar_init);
+module_exit(foobar_exit);
+
+MODULE_DESCRIPTION("lsm module logging to syslog");
+MODULE_LICENSE("GPL");

View file

@ -1,3 +1,15 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: reintroduce ATTR_FILE
The fsetattr patch removed ATTR_FILE but AppArmor needs it to distinguish
file based writes.
Note: Now that LSMs must be static, it would be better to add a file
pointer argument to security_operations->inode_setattr() instead. Then
move the fs.h chunk to patches.apparmor/fsetattr-restore-ia_file. -jeffm
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/open.c | 3 +++
include/linux/fs.h | 1 +
@ -5,7 +17,7 @@
--- a/fs/open.c
+++ b/fs/open.c
@@ -207,6 +207,9 @@ int do_truncate(struct dentry *dentry, s
@@ -208,6 +208,9 @@ int do_truncate(struct dentry *dentry, s
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | time_attrs;
@ -17,7 +29,7 @@
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -329,6 +329,7 @@ typedef void (dio_iodone_t)(struct kiocb
@@ -330,6 +330,7 @@ typedef void (dio_iodone_t)(struct kiocb
#define ATTR_ATTR_FLAG 1024
#define ATTR_KILL_SUID 2048
#define ATTR_KILL_SGID 4096

View file

@ -0,0 +1,58 @@
From: Jeff Mahoney <jeffm@suse.com>
Subject: [PATCH] vfs: restore ia_file for compatibility with external modules
References: bnc#381259
patches.apparmor/fsetattr.diff eliminated ia_file and ATTR_FILE in favor
of providing a ->fsetattr call that used a file pointer. Until this
patch is accepted into mainline, this patch provides the backward
compatibility for external file system modules.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
fs/attr.c | 13 ++++++++++++-
include/linux/fs.h | 11 +++++++++++
2 files changed, 23 insertions(+), 1 deletion(-)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -163,8 +163,19 @@ int fnotify_change(struct dentry *dentry
if (!error) {
if (file && file->f_op && file->f_op->fsetattr)
error = file->f_op->fsetattr(file, attr);
- else
+ else {
+ /* External file system still expect to be
+ * passed a file pointer via ia_file and
+ * have it announced via ATTR_FILE. This
+ * just makes it so they don't need to
+ * change their API just for us. External
+ * callers will have set these themselves. */
+ if (file) {
+ attr->ia_valid |= ATTR_FILE;
+ attr->ia_file = file;
+ }
error = inode->i_op->setattr(dentry, attr);
+ }
}
} else {
error = inode_change_ok(inode, attr);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -352,6 +352,17 @@ struct iattr {
struct timespec ia_atime;
struct timespec ia_mtime;
struct timespec ia_ctime;
+
+ /*
+ * Not an attribute, but an auxilary info for filesystems wanting to
+ * implement an ftruncate() like method. NOTE: filesystem should
+ * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
+ *
+ * NOTE: With patches.apparmor/fsetattr.diff applied, this is
+ * for compatibility with external file system modules only. There
+ * should not be any in-kernel users left.
+ */
+ struct file *ia_file;
};
/*

View file

@ -21,14 +21,14 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
fs/afs/file.c | 1 +
fs/afs/inode.c | 19 +++++++++++++++----
fs/afs/internal.h | 1 +
fs/attr.c | 18 ++++++++++++++----
fs/attr.c | 19 +++++++++++++++----
fs/fuse/dir.c | 20 +++++++++-----------
fs/fuse/file.c | 7 +++++++
fs/fuse/fuse_i.h | 4 ++++
fs/open.c | 20 ++++++++------------
fs/utimes.c | 2 +-
include/linux/fs.h | 10 ++--------
11 files changed, 63 insertions(+), 40 deletions(-)
11 files changed, 64 insertions(+), 40 deletions(-)
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@ -52,7 +52,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
const struct inode_operations afs_file_inode_operations = {
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -360,7 +360,8 @@ void afs_clear_inode(struct inode *inode
@@ -358,7 +358,8 @@ void afs_clear_inode(struct inode *inode
/*
* set the attributes of an inode
*/
@ -62,7 +62,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
{
struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
struct key *key;
@@ -382,8 +383,8 @@ int afs_setattr(struct dentry *dentry, s
@@ -380,8 +381,8 @@ int afs_setattr(struct dentry *dentry, s
afs_writeback_all(vnode);
}
@ -73,7 +73,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
} else {
key = afs_request_key(vnode->volume->cell);
if (IS_ERR(key)) {
@@ -393,10 +394,20 @@ int afs_setattr(struct dentry *dentry, s
@@ -391,10 +392,20 @@ int afs_setattr(struct dentry *dentry, s
}
ret = afs_vnode_setattr(vnode, key, attr);
@ -133,20 +133,22 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
} else {
error = inode_change_ok(inode, attr);
if (!error)
@@ -184,4 +188,10 @@ int notify_change(struct dentry *dentry,
@@ -183,5 +187,12 @@ int notify_change(struct dentry *dentry,
return error;
}
+EXPORT_SYMBOL_GPL(fnotify_change);
+
+int notify_change(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *attr)
+{
+ return fnotify_change(dentry, mnt, attr, NULL);
+}
+
EXPORT_SYMBOL(notify_change);
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1063,21 +1063,22 @@ static int fuse_dir_fsync(struct file *f
@@ -1064,21 +1064,22 @@ static int fuse_dir_fsync(struct file *f
return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
}
@ -172,7 +174,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
{
unsigned ivalid = iattr->ia_valid;
@@ -1096,7 +1097,7 @@ static void iattr_to_fattr(struct iattr
@@ -1097,7 +1098,7 @@ static void iattr_to_fattr(struct iattr
if (!(ivalid & ATTR_ATIME_SET))
arg->valid |= FATTR_ATIME_NOW;
}
@ -181,7 +183,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
arg->valid |= FATTR_MTIME;
arg->mtime = iattr->ia_mtime.tv_sec;
arg->mtimensec = iattr->ia_mtime.tv_nsec;
@@ -1113,8 +1114,8 @@ static void iattr_to_fattr(struct iattr
@@ -1158,8 +1159,8 @@ void fuse_release_nowrite(struct inode *
* vmtruncate() doesn't allow for this case, so do the rlimit checking
* and the actual truncation by hand.
*/
@ -192,7 +194,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
{
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1152,7 +1153,7 @@ static int fuse_do_setattr(struct dentry
@@ -1203,7 +1204,7 @@ static int fuse_do_setattr(struct dentry
memset(&inarg, 0, sizeof(inarg));
memset(&outarg, 0, sizeof(outarg));
@ -201,7 +203,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
if (file) {
struct fuse_file *ff = file->private_data;
inarg.valid |= FATTR_FH;
@@ -1194,10 +1195,7 @@ static int fuse_do_setattr(struct dentry
@@ -1273,10 +1274,7 @@ error:
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
{
@ -215,8 +217,8 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -907,6 +907,11 @@ static sector_t fuse_bmap(struct address
return err ? 0 : outarg.block;
@@ -1458,6 +1458,11 @@ static loff_t fuse_file_llseek(struct fi
return retval;
}
+static int fuse_fsetattr(struct file *file, struct iattr *attr)
@ -225,9 +227,9 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
+}
+
static const struct file_operations fuse_file_operations = {
.llseek = generic_file_llseek,
.llseek = fuse_file_llseek,
.read = do_sync_read,
@@ -920,6 +925,7 @@ static const struct file_operations fuse
@@ -1471,6 +1476,7 @@ static const struct file_operations fuse
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
@ -235,7 +237,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
.splice_read = generic_file_splice_read,
};
@@ -933,6 +939,7 @@ static const struct file_operations fuse
@@ -1484,6 +1490,7 @@ static const struct file_operations fuse
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
@ -245,7 +247,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -505,6 +505,10 @@ void fuse_change_attributes(struct inode
@@ -543,6 +543,10 @@ void fuse_truncate(struct address_space
*/
int fuse_dev_init(void);
@ -258,7 +260,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
*/
--- a/fs/open.c
+++ b/fs/open.c
@@ -206,16 +206,12 @@ int do_truncate(struct dentry *dentry, s
@@ -207,16 +207,12 @@ int do_truncate(struct dentry *dentry, s
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | time_attrs;
@ -276,7 +278,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
mutex_unlock(&dentry->d_inode->i_mutex);
return err;
}
@@ -583,7 +579,7 @@ asmlinkage long sys_fchmod(unsigned int
@@ -591,7 +587,7 @@ asmlinkage long sys_fchmod(unsigned int
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
@ -284,8 +286,8 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
+ err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);
out_putf:
@@ -633,7 +629,7 @@ asmlinkage long sys_chmod(const char __u
out_drop_write:
@@ -645,7 +641,7 @@ asmlinkage long sys_chmod(const char __u
}
static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
@ -294,7 +296,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
{
struct inode * inode;
int error;
@@ -663,7 +659,7 @@ static int chown_common(struct dentry *
@@ -672,7 +668,7 @@ static int chown_common(struct dentry *
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&inode->i_mutex);
@ -303,56 +305,56 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
mutex_unlock(&inode->i_mutex);
out:
return error;
@@ -677,7 +673,7 @@ asmlinkage long sys_chown(const char __u
error = user_path_walk(filename, &nd);
@@ -689,7 +685,7 @@ asmlinkage long sys_chown(const char __u
error = mnt_want_write(nd.path.mnt);
if (error)
goto out;
- error = chown_common(nd.dentry, nd.mnt, user, group);
+ error = chown_common(nd.dentry, nd.mnt, user, group, NULL);
path_release(&nd);
out:
return error;
@@ -697,7 +693,7 @@ asmlinkage long sys_fchownat(int dfd, co
error = __user_walk_fd(dfd, filename, follow, &nd);
goto out_release;
- error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
+ error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
mnt_drop_write(nd.path.mnt);
out_release:
path_put(&nd.path);
@@ -714,7 +710,7 @@ asmlinkage long sys_fchownat(int dfd, co
error = mnt_want_write(nd.path.mnt);
if (error)
goto out;
- error = chown_common(nd.dentry, nd.mnt, user, group);
+ error = chown_common(nd.dentry, nd.mnt, user, group, NULL);
path_release(&nd);
out:
return error;
@@ -711,7 +707,7 @@ asmlinkage long sys_lchown(const char __
error = user_path_walk_link(filename, &nd);
goto out_release;
- error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
+ error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
mnt_drop_write(nd.path.mnt);
out_release:
path_put(&nd.path);
@@ -733,7 +729,7 @@ asmlinkage long sys_lchown(const char __
error = mnt_want_write(nd.path.mnt);
if (error)
goto out;
- error = chown_common(nd.dentry, nd.mnt, user, group);
+ error = chown_common(nd.dentry, nd.mnt, user, group, NULL);
path_release(&nd);
out:
return error;
@@ -730,7 +726,7 @@ asmlinkage long sys_fchown(unsigned int
goto out_release;
- error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
+ error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
mnt_drop_write(nd.path.mnt);
out_release:
path_put(&nd.path);
@@ -757,7 +753,7 @@ asmlinkage long sys_fchown(unsigned int
goto out_fput;
dentry = file->f_path.dentry;
audit_inode(NULL, dentry);
- error = chown_common(dentry, file->f_path.mnt, user, group);
+ error = chown_common(dentry, file->f_path.mnt, user, group, file);
mnt_drop_write(file->f_path.mnt);
out_fput:
fput(file);
out:
return error;
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -132,7 +132,7 @@ long do_utimes(int dfd, char __user *fil
@@ -151,7 +151,7 @@ long do_utimes(int dfd, char __user *fil
}
}
mutex_lock(&inode->i_mutex);
- error = notify_change(path.dentry, path.mnt, &newattrs);
+ error = fnotify_change(path.dentry, path.mnt, &newattrs, f);
mutex_unlock(&inode->i_mutex);
dput_and_out:
if (f)
mnt_drop_write_and_out:
mnt_drop_write(path.mnt);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -329,7 +329,6 @@ typedef void (dio_iodone_t)(struct kiocb
@@ -330,7 +330,6 @@ typedef void (dio_iodone_t)(struct kiocb
#define ATTR_ATTR_FLAG 1024
#define ATTR_KILL_SUID 2048
#define ATTR_KILL_SGID 4096
@ -360,7 +362,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
#define ATTR_KILL_PRIV 16384
#define ATTR_OPEN 32768 /* Truncating from open(O_TRUNC) */
@@ -351,13 +350,6 @@ struct iattr {
@@ -352,13 +351,6 @@ struct iattr {
struct timespec ia_atime;
struct timespec ia_mtime;
struct timespec ia_ctime;
@ -374,7 +376,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
};
/*
@@ -1188,6 +1180,7 @@ struct file_operations {
@@ -1244,6 +1236,7 @@ struct file_operations {
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
@ -382,7 +384,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de> ---
};
struct inode_operations {
@@ -1694,6 +1687,7 @@ extern int do_remount_sb(struct super_bl
@@ -1752,6 +1745,7 @@ extern int do_remount_sb(struct super_bl
extern sector_t bmap(struct inode *, sector_t);
#endif
extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);

View file

@ -1,39 +0,0 @@
---
security/apparmor/apparmor.h | 5 +++--
security/apparmor/main.c | 9 +++++++++
2 files changed, 12 insertions(+), 2 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -68,10 +68,11 @@
#define AA_ALL_EXEC_MODS (AA_USER_EXEC_MODS | \
AA_OTHER_EXEC_MODS)
-/* shared permissions that are not duplicated in user:group:other */
+/* shared permissions that are not duplicated in user::other */
+#define AA_CHANGE_HAT 0x20000000
#define AA_CHANGE_PROFILE 0x40000000
-#define AA_SHARED_PERMS (AA_CHANGE_PROFILE)
+#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_SHARED_PERMS)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -1300,6 +1300,15 @@ repeat:
if (hat_name) {
char *name, *profile_name;
+ /* Not Yet. This perm check is currently done by searching
+ for the hat profile. When hat style profile names
+ become more generic then this will be needed.
+ if (!(aa_match(profile->file_rules, hat_name) &
+ AA_CHANGE_PROFILE)) {
+ error = -EACCES;
+ goto out;
+ }
+ */
if (previous_profile)
profile_name = previous_profile->name;
else

View file

@ -1,86 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Remove redundant may_create() argument
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/namei.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1462,16 +1462,14 @@ static int may_delete(struct inode *dir,
* 3. We should have write and exec permissions on dir
* 4. We can't do it if dir is immutable (done in permission())
*/
-static inline int may_create(struct inode *dir, struct dentry *child,
- struct nameidata2 *nd)
+static inline int may_create(struct nameidata2 *nd, struct dentry *child)
{
if (child->d_inode)
return -EEXIST;
- if (IS_DEADDIR(dir))
+ if (IS_DEADDIR(nd->dentry->d_inode))
return -ENOENT;
- if (nd)
- nd->flags |= LOOKUP_CONTINUE;
- return permission(dir,MAY_WRITE | MAY_EXEC, nd);
+ nd->flags |= LOOKUP_CONTINUE;
+ return permission(nd->dentry->d_inode, MAY_WRITE | MAY_EXEC, nd);
}
/*
@@ -1537,7 +1535,7 @@ void unlock_rename(struct dentry *p1, st
int vfs_create(struct nameidata2 *nd, struct dentry *dentry, int mode)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_create(dir, dentry, nd);
+ int error = may_create(nd, dentry);
if (error)
return error;
@@ -1883,7 +1881,7 @@ EXPORT_SYMBOL_GPL(lookup_create);
int vfs_mknod(struct nameidata2 *nd, struct dentry *dentry, int mode, dev_t dev)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_create(dir, dentry, nd);
+ int error = may_create(nd, dentry);
if (error)
return error;
@@ -1963,7 +1961,7 @@ asmlinkage long sys_mknod(const char __u
int vfs_mkdir(struct nameidata2 *nd, struct dentry *dentry, int mode)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_create(dir, dentry, nd);
+ int error = may_create(nd, dentry);
if (error)
return error;
@@ -2232,7 +2230,7 @@ int vfs_symlink(struct nameidata2 *nd, s
const char *oldname, int mode)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_create(dir, dentry, nd);
+ int error = may_create(nd, dentry);
if (error)
return error;
@@ -2304,7 +2302,7 @@ int vfs_link(struct nameidata2 *old_nd,
if (!inode)
return -ENOENT;
- error = may_create(dir, new_dentry, new_parent);
+ error = may_create(new_parent, new_dentry);
if (error)
return error;
@@ -2522,7 +2520,7 @@ int vfs_rename(struct nameidata2 *old_nd
return error;
if (!new_dentry->d_inode)
- error = may_create(new_dir, new_dentry, new_nd);
+ error = may_create(new_nd, new_dentry);
else
error = may_delete(new_dir, new_dentry, is_dir);
if (error)

View file

@ -1,74 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Pass nameidata2 to may_delete()
Pass the nameidata through to may_delete(), and pass it on to the
permission() call.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/namei.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1418,8 +1418,9 @@ static inline int check_sticky(struct in
* 10. We don't allow removal of NFS sillyrenamed files; it's handled by
* nfs_async_unlink().
*/
-static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
+static int may_delete(struct nameidata2 *nd, struct dentry *victim, int isdir)
{
+ struct inode *dir = nd->dentry->d_inode;
int error;
if (!victim->d_inode)
@@ -1428,11 +1429,8 @@ static int may_delete(struct inode *dir,
BUG_ON(victim->d_parent->d_inode != dir);
audit_inode_child(victim->d_name.name, victim->d_inode, dir);
-#if 0
- if (nd)
- nd->flags |= LOOKUP_CONTINUE;
-#endif
- error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
+ nd->flags |= LOOKUP_CONTINUE;
+ error = permission(dir,MAY_WRITE | MAY_EXEC, nd);
if (error)
return error;
if (IS_APPEND(dir))
@@ -2049,7 +2047,7 @@ void dentry_unhash(struct dentry *dentry
int vfs_rmdir(struct nameidata2 *nd, struct dentry *dentry)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_delete(dir, dentry, 1);
+ int error = may_delete(nd, dentry, 1);
if (error)
return error;
@@ -2131,7 +2129,7 @@ asmlinkage long sys_rmdir(const char __u
int vfs_unlink(struct nameidata2 *nd, struct dentry *dentry)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_delete(dir, dentry, 0);
+ int error = may_delete(nd, dentry, 0);
if (error)
return error;
@@ -2517,14 +2515,14 @@ int vfs_rename(struct nameidata2 *old_nd
if (old_dentry->d_inode == new_dentry->d_inode)
return 0;
- error = may_delete(old_dir, old_dentry, is_dir);
+ error = may_delete(old_nd, old_dentry, is_dir);
if (error)
return error;
if (!new_dentry->d_inode)
error = may_create(new_nd, new_dentry);
else
- error = may_delete(new_dir, new_dentry, is_dir);
+ error = may_delete(new_nd, new_dentry, is_dir);
if (error)
return error;

View file

@ -1,60 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Make d_path() consistent across mount operations
The path that __d_path() computes can become slightly inconsistent when it
races with mount operations: it grabs the vfsmount_lock when traversing mount
points but immediately drops it again, only to re-grab it when it reaches the
next mount point. The result is that the filename computed is not always
consisent, and the file may never have had that name. (This is unlikely, but
still possible.)
Fix this by grabbing the vfsmount_lock when the first mount point is reached,
and holding onto it until the d_cache lookup is completed.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1786,7 +1786,7 @@ static char *__d_path(struct dentry *den
struct dentry *root, struct vfsmount *rootmnt,
char *buffer, int buflen, int fail_deleted)
{
- int namelen, is_slash;
+ int namelen, is_slash, vfsmount_locked = 0;
if (buflen < 2)
return ERR_PTR(-ENAMETOOLONG);
@@ -1809,14 +1809,14 @@ static char *__d_path(struct dentry *den
struct dentry * parent;
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
- spin_lock(&vfsmount_lock);
- if (vfsmnt->mnt_parent == vfsmnt) {
- spin_unlock(&vfsmount_lock);
- goto global_root;
+ if (!vfsmount_locked) {
+ spin_lock(&vfsmount_lock);
+ vfsmount_locked = 1;
}
+ if (vfsmnt->mnt_parent == vfsmnt)
+ goto global_root;
dentry = vfsmnt->mnt_mountpoint;
vfsmnt = vfsmnt->mnt_parent;
- spin_unlock(&vfsmount_lock);
continue;
}
parent = dentry->d_parent;
@@ -1835,6 +1835,8 @@ static char *__d_path(struct dentry *den
*--buffer = '/';
out:
+ if (vfsmount_locked)
+ spin_unlock(&vfsmount_lock);
spin_unlock(&dcache_lock);
return buffer;

View file

@ -1,47 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: nfs NULL nameidata check?
nfs_lookup() checks for NULL nameidata in one place, but not in another. In
nfs_sillyrename() it calls lookup_one_len() -> __lookup_hash(), which passes
in a NULL nameidata to nfs_lookup(). Unless I'm overlooking something,
fs/nfs/dir.c:923 will dereference this NULL pointer if the sillyrenamed file
exists?
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/nfs/dir.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -896,15 +896,15 @@ int nfs_is_exclusive_create(struct inode
return (nd->intent.open.flags & O_EXCL) != 0;
}
-static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir,
+static inline int nfs_reval_fsid(struct nameidata *nd, struct inode *dir,
struct nfs_fh *fh, struct nfs_fattr *fattr)
{
struct nfs_server *server = NFS_SERVER(dir);
- if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
- /* Revalidate fsid on root dir */
- return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode);
- return 0;
+ if (nd == NULL || nfs_fsid_equal(&server->fsid, &fattr->fsid))
+ return 0;
+ /* Revalidate fsid on root dir */
+ return __nfs_revalidate_inode(server, nd->mnt->mnt_root->d_inode);
}
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata2 *nd)
@@ -945,7 +945,7 @@ static struct dentry *nfs_lookup(struct
res = ERR_PTR(error);
goto out_unlock;
}
- error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr);
+ error = nfs_reval_fsid(nd, dir, &fhandle, &fattr);
if (error < 0) {
res = ERR_PTR(error);
goto out_unlock;

View file

@ -1,45 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Pass nameidata2 to permission() from nfsd_permission()
Construct a nameidata object and pass it down to permission(), so
that we can do the proper mount flag checks there.
Note that confining nfsd with AppArmor makes no sense, and so this
patch is not necessary for AppArmor alone.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/nfsd/vfs.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1804,6 +1804,7 @@ nfsd_statfs(struct svc_rqst *rqstp, stru
__be32
nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
{
+ struct nameidata2 nd;
struct inode *inode = dentry->d_inode;
int err;
@@ -1869,12 +1870,16 @@ nfsd_permission(struct svc_export *exp,
inode->i_uid == current->fsuid)
return 0;
- err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
+ nd.dentry = dentry;
+ nd.mnt = exp->ex_mnt;
+ nd.flags = LOOKUP_ACCESS;
+
+ err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), &nd);
/* Allow read access to binaries even when mode 111 */
if (err == -EACCES && S_ISREG(inode->i_mode) &&
acc == (MAY_READ | MAY_OWNER_OVERRIDE))
- err = permission(inode, MAY_EXEC, NULL);
+ err = permission(inode, MAY_EXEC, &nd);
return err? nfserrno(err) : 0;
}

View file

@ -1,139 +0,0 @@
---
security/apparmor/apparmor.h | 21 ++++++++++-----------
security/apparmor/main.c | 40 ++++++++++++----------------------------
security/apparmor/match.c | 9 +++++++--
3 files changed, 29 insertions(+), 41 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -42,15 +42,18 @@
AA_EXEC_MOD_2 | AA_EXEC_MOD_3 | \
AA_EXEC_MOD_4)
+#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
+ AA_EXEC_MOD_2 | AA_EXEC_MOD_3 | \
+ AA_EXEC_MOD_4)
+
+#define AA_EXEC_TYPE (MAY_EXEC | AA_EXEC_UNSAFE | \
+ AA_EXEC_MODIFIERS)
+
#define AA_EXEC_UNCONFINED AA_EXEC_MOD_0
#define AA_EXEC_INHERIT AA_EXEC_MOD_1
#define AA_EXEC_PROFILE (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
#define AA_EXEC_PIX AA_EXEC_MOD_2
-#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
- AA_EXEC_MOD_2 | AA_EXEC_MOD_3 | \
- AA_EXEC_MOD_4)
-
#define AA_USER_SHIFT 0
#define AA_OTHER_SHIFT 14
@@ -65,16 +68,12 @@
#define AA_USER_EXEC (MAY_EXEC << AA_USER_SHIFT)
#define AA_OTHER_EXEC (MAY_EXEC << AA_OTHER_SHIFT)
-#define AA_USER_EXEC_MODS (AA_EXEC_MODIFIERS << AA_USER_SHIFT)
-#define AA_OTHER_EXEC_MODS (AA_EXEC_MODIFIERS << AA_OTHER_SHIFT)
-
-#define AA_USER_EXEC_UNSAFE (AA_EXEC_UNSAFE << AA_USER_SHIFT)
-#define AA_OTHER_EXEC_UNSAFE (AA_EXEC_UNSAFE << AA_OTHER_SHIFT)
+#define AA_USER_EXEC_TYPE (AA_EXEC_TYPE << AA_USER_SHIFT)
+#define AA_OTHER_EXEC_TYPE (AA_EXEC_TYPE << AA_OTHER_SHIFT)
#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC)
-#define AA_ALL_EXEC_MODS (AA_USER_EXEC_MODS | \
- AA_OTHER_EXEC_MODS)
+#define ALL_AA_EXEC_TYPE (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
/* overloaded permissions for link pairs */
#define AA_LINK_SUBSET_TEST 0x0020
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -68,7 +68,7 @@ static int aa_link_denied(struct aa_prof
int *request_mask)
{
unsigned int state;
- int l_mode, t_mode, l_subset, denied_mask = 0;
+ int l_mode, t_mode, denied_mask = 0;
int link_mask = AA_MAY_LINK << target_mode;
*request_mask = link_mask;
@@ -90,7 +90,7 @@ static int aa_link_denied(struct aa_prof
/* Do link perm subset test
* If a subset test is required a permission subset test of the
- * perms for the link are done against the user:group:other of the
+ * perms for the link are done against the user::other of the
* target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
*
* If the link has 'x', an exact match of all the execute flags
@@ -100,38 +100,22 @@ static int aa_link_denied(struct aa_prof
t_mode = aa_match(profile->file_rules, target);
-
/* For actual subset test ignore valid-profile-transition flags,
* and link bits
*/
- l_mode &= ~(AA_SHARED_PERMS | AA_LINK_BITS);
- t_mode &= ~(AA_SHARED_PERMS | AA_LINK_BITS);
- l_subset = l_mode & AA_FILE_PERMS;
+ l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
+ t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
*request_mask = l_mode | link_mask;
- if (l_subset) {
- denied_mask |= (l_subset) & ~t_mode;
- if (denied_mask & AA_EXEC_BITS)
- denied_mask |= l_mode & AA_ALL_EXEC_MODS;
- else if (l_mode & AA_EXEC_BITS) {
- if (!(l_mode & AA_USER_EXEC_UNSAFE))
- l_mode |= t_mode & AA_USER_EXEC_UNSAFE;
- if (l_mode & AA_USER_EXEC &&
- (l_mode & AA_USER_EXEC_MODS) !=
- (t_mode & AA_USER_EXEC_MODS))
- denied_mask |= AA_USER_EXEC |
- (l_mode & AA_USER_EXEC_MODS);
- if (!(l_mode & AA_OTHER_EXEC_UNSAFE))
- l_mode |= t_mode & AA_OTHER_EXEC_UNSAFE;
- if (l_mode & AA_OTHER_EXEC &&
- (l_mode & AA_OTHER_EXEC_MODS) !=
- (t_mode & AA_OTHER_EXEC_MODS))
- denied_mask |= AA_OTHER_EXEC |
- (l_mode & AA_OTHER_EXEC_MODS);
- }
- } else if (t_mode & AA_FILE_PERMS)
- denied_mask |= t_mode | link_mask;
+ if (l_mode) {
+ denied_mask |= l_mode & ~t_mode;
+ if ((l_mode & AA_EXEC_BITS) &&
+ (l_mode & ALL_AA_EXEC_TYPE) !=
+ (t_mode & ALL_AA_EXEC_TYPE))
+ denied_mask = (denied_mask & ~ALL_AA_EXEC_TYPE) |
+ (l_mode & ALL_AA_EXEC_TYPE);
+ }
return denied_mask;
}
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -175,9 +175,14 @@ int verify_dfa(struct aa_dfa *dfa)
for (i = 0; i < state_count; i++) {
int mode = ACCEPT_TABLE(dfa)[i];
- if (mode & ~AA_VALID_PERM_MASK) {
+ if (mode & ~AA_VALID_PERM_MASK)
+ goto out;
+
+ /* if any exec modifier is set MAY_EXEC must be set */
+ if ((mode & AA_USER_EXEC_TYPE) && !(mode & AA_USER_EXEC))
+ goto out;
+ if ((mode & AA_OTHER_EXEC_TYPE) && !(mode & AA_OTHER_EXEC))
goto out;
- }
}
error = 0;

View file

@ -1,3 +0,0 @@
obj-$(CONFIG_SECURITY_FOOBAR) += foobar.o
foobar-y := foobar-lsm.o

View file

@ -1 +0,0 @@
obj-m += foobar.o

View file

@ -1,197 +0,0 @@
#include <linux/security.h>
#include <linux/module.h>
#include <linux/namei.h>
static void log_path(char *op, struct dentry *dentry, struct vfsmount *mnt)
{
char *page, *name;
if (!mnt) {
printk(KERN_INFO "foobar(%s): %p NULL vfsmnt\n", op, dentry);
return;
}
page = (char *)__get_free_page(GFP_KERNEL);
if (!page) {
printk(KERN_ERR "foobar(%s): Unable to get page for path %p/%p\n",
op, mnt, dentry);
goto out;
}
name=d_path(dentry, mnt, page, PAGE_SIZE);
if (IS_ERR(name)){
printk(KERN_ERR "foobar(%s): Error path %p/%p overflowed buffer\n",
op, mnt, dentry);
goto out;
}
printk(KERN_INFO "foobar(%s): %p/%p->'%s'\n",
op, mnt, dentry, name);
out:
if (page)
free_page((unsigned long)page);
}
static int foobar_inode_mkdir(struct inode *inode, struct dentry *dentry,
struct vfsmount *mnt, int mask)
{
log_path("inode_mkdir", dentry, mnt);
return 0;
}
static int foobar_inode_rmdir(struct inode *inode, struct dentry *dentry,
struct vfsmount *mnt)
{
log_path("inode_rmdir", dentry, mnt);
return 0;
}
static int foobar_inode_create(struct inode *inode, struct dentry *dentry,
struct vfsmount *mnt, int mask)
{
log_path("inode_create", dentry, mnt);
return 0;
}
static int foobar_inode_link(struct dentry *old_dentry,
struct vfsmount *old_mnt,
struct inode *inode,
struct dentry *new_dentry,
struct vfsmount *new_mnt)
{
log_path("inode_link (old)", old_dentry, old_mnt);
log_path("inode_link (new)", new_dentry, new_mnt);
return 0;
}
static int foobar_inode_unlink(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt)
{
log_path("inode_unlink", dentry, mnt);
return 0;
}
static int foobar_inode_mknod(struct inode *inode, struct dentry *dentry,
struct vfsmount *mnt, int mode, dev_t dev)
{
log_path("inode_mknod", dentry, mnt);
return 0;
}
static int foobar_inode_rename(struct inode *old_inode,
struct dentry *old_dentry,
struct vfsmount *old_mnt,
struct inode *new_inode,
struct dentry *new_dentry,
struct vfsmount *new_mnt)
{
log_path("inode_rename (old)", old_dentry, old_mnt);
log_path("inode_rename (new)", new_dentry, new_mnt);
return 0;
}
static int foobar_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
struct iattr *iattr)
{
log_path("inode_setattr", dentry, mnt);
return 0;
}
static int foobar_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
int flags)
{
log_path("inode_setxattr", dentry, mnt);
return 0;
}
static int foobar_inode_getxattr(struct dentry *dentry,
struct vfsmount *mnt, char *name)
{
log_path("inode_getxattr", dentry, mnt);
return 0;
}
static int foobar_inode_listxattr(struct dentry *dentry,
struct vfsmount *mnt)
{
log_path("inode_listxattr", dentry, mnt);
return 0;
}
static int foobar_inode_removexattr(struct dentry *dentry,
struct vfsmount *mnt, char *name)
{
log_path("inode_removexattr", dentry, mnt);
return 0;
}
static int foobar_inode_symlink(struct inode *dir,
struct dentry *dentry, struct vfsmount *mnt,
const char *old_name)
{
log_path("inode_symlink", dentry, mnt);
return 0;
}
static int foobar_inode_permission(struct inode *inode, int mask,
struct nameidata *nd)
{
log_path("inode_permission", nd->dentry, nd->mnt);
return 0;
}
struct security_operations foobar_ops = {
.inode_create = foobar_inode_create,
.inode_link = foobar_inode_link,
.inode_unlink = foobar_inode_unlink,
.inode_mkdir = foobar_inode_mkdir,
.inode_rmdir = foobar_inode_rmdir,
.inode_mknod = foobar_inode_mknod,
.inode_rename = foobar_inode_rename,
.inode_setattr = foobar_inode_setattr,
.inode_setxattr = foobar_inode_setxattr,
.inode_getxattr = foobar_inode_getxattr,
.inode_listxattr = foobar_inode_listxattr,
.inode_removexattr = foobar_inode_removexattr,
.inode_symlink = foobar_inode_symlink,
// .inode_permission = foobar_inode_permission,
};
static int __init foobar_init(void)
{
int error;
if ((error = register_security(&foobar_ops))) {
printk(KERN_ERR "Unable to load dummy module\n");
}
return error;
}
static void __exit foobar_exit(void)
{
if (unregister_security(&foobar_ops))
printk(KERN_ERR "Unable to properly unregister module\n");
}
module_init(foobar_init);
module_exit(foobar_exit);
MODULE_DESCRIPTION("Test module");
MODULE_LICENSE("GPL");

View file

@ -1,561 +0,0 @@
---
security/apparmor/apparmor.h | 60 +++++++---
security/apparmor/apparmorfs.c | 2
security/apparmor/lsm.c | 2
security/apparmor/main.c | 193 +++++++++++++++++++++++------------
security/apparmor/match.c | 8 -
security/apparmor/module_interface.c | 3
6 files changed, 179 insertions(+), 89 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -26,22 +26,50 @@
#define AA_MAY_LINK 0x0010
#define AA_MAY_LOCK 0x0020
#define AA_EXEC_MMAP 0x0040
+#define AA_EXEC_UNSAFE 0x0080
+#define AA_EXEC_MOD_0 0x0100
+#define AA_EXEC_MOD_1 0x0200
+#define AA_BASE_PERMS (MAY_READ | MAY_WRITE | MAY_EXEC | \
+ MAY_APPEND | AA_MAY_LINK | \
+ AA_MAY_LOCK | AA_EXEC_MMAP | \
+ AA_EXEC_UNSAFE | AA_EXEC_MOD_0 | \
+ AA_EXEC_MOD_1)
-#define AA_CHANGE_PROFILE 0x04000000
-#define AA_EXEC_INHERIT 0x08000000
-#define AA_EXEC_UNCONFINED 0x10000000
-#define AA_EXEC_PROFILE 0x20000000
-#define AA_EXEC_UNSAFE 0x40000000
-
-#define AA_EXEC_MODIFIERS (AA_EXEC_INHERIT | \
- AA_EXEC_UNCONFINED | \
- AA_EXEC_PROFILE)
+#define AA_EXEC_UNCONFINED 0
+#define AA_EXEC_INHERIT AA_EXEC_MOD_0
+#define AA_EXEC_PROFILE AA_EXEC_MOD_1
+#define AA_EXEC_PIX (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
-#define AA_VALID_PERM_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | \
- MAY_APPEND | AA_MAY_LINK | \
- AA_MAY_LOCK | \
- AA_EXEC_MODIFIERS | AA_EXEC_MMAP | \
- AA_EXEC_UNSAFE | AA_CHANGE_PROFILE)
+#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
+
+#define AA_USER_SHIFT 0
+#define AA_OTHER_SHIFT 10
+
+#define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT)
+#define AA_OTHER_PERMS (AA_BASE_PERMS << AA_OTHER_SHIFT)
+
+#define AA_FILE_PERMS (AA_USER_PERMS | AA_OTHER_PERMS)
+
+#define AA_LINK_BITS ((AA_MAY_LINK << AA_USER_SHIFT) | \
+ (AA_MAY_LINK << AA_OTHER_SHIFT))
+
+#define AA_USER_EXEC (MAY_EXEC << AA_USER_SHIFT)
+#define AA_OTHER_EXEC (MAY_EXEC << AA_OTHER_SHIFT)
+
+#define AA_USER_EXEC_MODS (AA_EXEC_MODIFIERS << AA_USER_SHIFT)
+#define AA_OTHER_EXEC_MODS (AA_EXEC_MODIFIERS << AA_OTHER_SHIFT)
+
+#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC)
+
+#define AA_ALL_EXEC_MODS (AA_USER_EXEC_MODS | \
+ AA_OTHER_EXEC_MODS)
+
+/* shared permissions that are not duplicated in user:group:other */
+#define AA_CHANGE_PROFILE 0x40000000
+
+#define AA_SHARED_PERMS (AA_CHANGE_PROFILE)
+
+#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_SHARED_PERMS)
#define AA_SECURE_EXEC_NEEDED 1
@@ -183,7 +211,7 @@ struct aa_audit {
const char *name;
const char *name2;
const char *name3;
- int requested_mask, denied_mask;
+ int request_mask, denied_mask;
struct iattr *iattr;
pid_t task, parent;
int family, type, protocol;
@@ -226,7 +254,7 @@ extern int aa_perm_dir(struct aa_profile
struct dentry *dentry, struct vfsmount *mnt,
int mask);
extern int aa_perm_path(struct aa_profile *, const char *operation,
- const char *name, int);
+ const char *name, int mask, uid_t uid);
extern int aa_link(struct aa_profile *profile,
struct dentry *link, struct vfsmount *link_mnt,
struct dentry *target, struct vfsmount *target_mnt);
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -89,7 +89,7 @@ static struct file_operations apparmorfs
static ssize_t aa_matching_read(struct file *file, char __user *buf,
size_t size, loff_t *ppos)
{
- const char *matching = "pattern=aadfa perms=rwxamlz";
+ const char *matching = "pattern=aadfa perms=rwxamlz user:other";
return simple_read_from_buffer(buf, size, ppos, matching,
strlen(matching));
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -199,7 +199,7 @@ static int apparmor_sysctl(struct ctl_ta
if (name && name - buffer >= 5) {
name -= 5;
memcpy(name, "/proc", 5);
- error = aa_perm_path(profile, "sysctl", name, mask);
+ error = aa_perm_path(profile, "sysctl", name, mask, 0);
}
free_page((unsigned long)buffer);
}
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -31,6 +31,14 @@ static const char *capability_names[] =
struct aa_namespace *default_namespace;
+static int aa_inode_mode(struct inode *inode)
+{
+ /* if the inode doesn't exist the user is creating it */
+ if (!inode || current->fsuid == inode->i_uid)
+ return AA_USER_SHIFT;
+ return AA_OTHER_SHIFT;
+}
+
/**
* aa_file_denied - check for @mask access on a file
* @profile: profile to check against
@@ -51,39 +59,52 @@ static int aa_file_denied(struct aa_prof
* @profile: profile to check against
* @link: pathname of link being created
* @target: pathname of target to be linked to
+ * @target_mode: UGO shift for target inode
* @request_mask: the permissions subset valid only if link succeeds
* Return %0 on success, or else the permissions that the profile denies.
*/
static int aa_link_denied(struct aa_profile *profile, const char *link,
- const char *target, int *request_mask)
+ const char *target, int target_mode,
+ int *request_mask)
{
int l_mode, t_mode, denied_mask;
+ int link_mask = AA_MAY_LINK << target_mode;
l_mode = aa_match(profile->file_rules, link);
t_mode = aa_match(profile->file_rules, target);
/* Ignore valid-profile-transition flags. */
- l_mode &= ~AA_CHANGE_PROFILE;
- t_mode &= ~AA_CHANGE_PROFILE;
+ l_mode &= ~AA_SHARED_PERMS;
+ t_mode &= ~AA_SHARED_PERMS;
- *request_mask = l_mode | AA_MAY_LINK;
-
- /* Link always requires 'l' on the link, a subset of the
- * target's 'r', 'w', 'x', 'a', 'z', and 'm' permissions on the link,
- * and if the link has 'x', an exact match of all the execute flags
- * ('i', 'u', 'U', 'p', 'P').
- */
-#define RWXAZM (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND | AA_MAY_LOCK | \
- AA_EXEC_MMAP)
- denied_mask = ~l_mode & AA_MAY_LINK;
- if (l_mode & RWXAZM)
- denied_mask |= (l_mode & ~ AA_MAY_LINK) & ~t_mode;
- else
- denied_mask |= t_mode | AA_MAY_LINK;
- if (denied_mask & AA_EXEC_MODIFIERS)
- denied_mask |= MAY_EXEC;
+ *request_mask = l_mode | link_mask;
-#undef RWXAZM
+ /* Link always requires 'l' on the link, a subset for user:other
+ * of the target's 'r', 'w', 'x', 'a', 'z', and 'm' permissions on
+ * the link, and if the link has 'x', an exact match of all the
+ * execute flags ('i', 'u', 'U', 'p', 'P').
+ */
+#define SUBSET_PERMS (AA_FILE_PERMS & ~AA_LINK_BITS)
+ denied_mask = ~l_mode & link_mask;
+ if (l_mode & SUBSET_PERMS) {
+ denied_mask |= (l_mode & SUBSET_PERMS) & ~t_mode;
+ if (denied_mask & AA_EXEC_BITS)
+ denied_mask |= l_mode & AA_ALL_EXEC_MODS;
+ else if (l_mode & AA_EXEC_BITS) {
+ if (l_mode & AA_USER_EXEC &&
+ (l_mode & AA_USER_EXEC_MODS) !=
+ (t_mode & AA_USER_EXEC_MODS))
+ denied_mask |= AA_USER_EXEC |
+ (l_mode & AA_USER_EXEC_MODS);
+ if (l_mode & AA_OTHER_EXEC &&
+ (l_mode & AA_OTHER_EXEC_MODS) !=
+ (t_mode & AA_OTHER_EXEC_MODS))
+ denied_mask |= AA_OTHER_EXEC |
+ (l_mode & AA_OTHER_EXEC_MODS);
+ }
+ } else
+ denied_mask |= t_mode | link_mask;
+#undef SUBSET_PERMS
return denied_mask;
}
@@ -173,7 +194,7 @@ static int aa_perm_dentry(struct aa_prof
char *buffer = NULL;
sa->name = aa_get_name(dentry, mnt, &buffer, check);
-
+ sa->request_mask <<= aa_inode_mode(dentry->d_inode);
if (IS_ERR(sa->name)) {
/*
* deleted files are given a pass on permission checks when
@@ -182,13 +203,13 @@ static int aa_perm_dentry(struct aa_prof
if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
sa->denied_mask = 0;
else {
- sa->denied_mask = sa->requested_mask;
+ sa->denied_mask = sa->request_mask;
sa->error_code = PTR_ERR(sa->name);
}
sa->name = NULL;
} else
sa->denied_mask = aa_file_denied(profile, sa->name,
- sa->requested_mask);
+ sa->request_mask);
if (!sa->denied_mask)
sa->error_code = 0;
@@ -229,10 +250,10 @@ void free_default_namespace(void)
default_namespace = NULL;
}
-static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
- int mask)
+static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
+ int mask)
{
- char mask_str[10], *m = mask_str;
+ char *m = buffer;
if (mask & AA_EXEC_MMAP)
*m++ = 'm';
@@ -242,32 +263,58 @@ static void aa_audit_file_mask(struct au
*m++ = 'w';
else if (mask & MAY_APPEND)
*m++ = 'a';
- if (mask & (MAY_EXEC | AA_EXEC_MODIFIERS)) {
+ if (mask & MAY_EXEC) {
if (mask & AA_EXEC_UNSAFE) {
- if (mask & AA_EXEC_INHERIT)
- *m++ = 'i';
- if (mask & AA_EXEC_UNCONFINED)
+ switch(mask & AA_EXEC_MODIFIERS) {
+ case AA_EXEC_UNCONFINED:
*m++ = 'u';
- if (mask & AA_EXEC_PROFILE)
+ break;
+ case AA_EXEC_PIX:
+ *m++ = 'p';
+ /* fall through */
+ case AA_EXEC_INHERIT:
+ *m++ = 'i';
+ break;
+ case AA_EXEC_PROFILE:
*m++ = 'p';
+ break;
+ }
} else {
- if (mask & AA_EXEC_INHERIT)
- *m++ = 'I';
- if (mask & AA_EXEC_UNCONFINED)
+ switch(mask & AA_EXEC_MODIFIERS) {
+ case AA_EXEC_UNCONFINED:
*m++ = 'U';
- if (mask & AA_EXEC_PROFILE)
+ break;
+ case AA_EXEC_PIX:
*m++ = 'P';
+ /* fall through */
+ case AA_EXEC_INHERIT:
+ *m++ = 'I';
+ break;
+ case AA_EXEC_PROFILE:
+ *m++ = 'P';
+ break;
+ }
}
- if (mask & MAY_EXEC)
- *m++ = 'x';
+ *m++ = 'x';
}
if (mask & AA_MAY_LINK)
*m++ = 'l';
if (mask & AA_MAY_LOCK)
*m++ = 'k';
*m++ = '\0';
+}
+
+static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
+ int mask)
+{
+ char user[10], other[10];
- audit_log_format(ab, " %s=\"%s\"", name, mask_str);
+ aa_audit_file_sub_mask(ab, user,
+ (mask & AA_USER_PERMS) >> AA_USER_SHIFT);
+ aa_audit_file_sub_mask(ab, other,
+ (mask & AA_OTHER_PERMS) >> AA_OTHER_SHIFT);
+
+ audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
}
static const char *address_families[] = {
@@ -316,8 +363,8 @@ static int aa_audit_base(struct aa_profi
if (sa->info)
audit_log_format(ab, " info=\"%s\"", sa->info);
- if (sa->requested_mask)
- aa_audit_file_mask(ab, "requested_mask", sa->requested_mask);
+ if (sa->request_mask)
+ aa_audit_file_mask(ab, "request_mask", sa->request_mask);
if (sa->denied_mask)
aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);
@@ -472,7 +519,7 @@ int aa_attr(struct aa_profile *profile,
sa.operation = "setattr";
sa.gfp_mask = GFP_KERNEL;
sa.iattr = iattr;
- sa.requested_mask = MAY_WRITE;
+ sa.request_mask = MAY_WRITE;
sa.error_code = -EACCES;
check = 0;
@@ -506,7 +553,7 @@ int aa_perm_xattr(struct aa_profile *pro
memset(&sa, 0, sizeof(sa));
sa.operation = operation;
sa.gfp_mask = GFP_KERNEL;
- sa.requested_mask = mask;
+ sa.request_mask = mask;
sa.error_code = -EACCES;
if (inode && S_ISDIR(inode->i_mode))
@@ -540,7 +587,7 @@ int aa_perm(struct aa_profile *profile,
memset(&sa, 0, sizeof(sa));
sa.operation = operation;
sa.gfp_mask = GFP_KERNEL;
- sa.requested_mask = mask;
+ sa.request_mask = mask;
sa.error_code = -EACCES;
error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
@@ -569,24 +616,28 @@ int aa_perm_dir(struct aa_profile *profi
memset(&sa, 0, sizeof(sa));
sa.operation = operation;
sa.gfp_mask = GFP_KERNEL;
- sa.requested_mask = mask;
+ sa.request_mask = mask;
sa.error_code = -EACCES;
return aa_perm_dentry(profile, dentry, mnt, &sa, AA_CHECK_DIR);
}
int aa_perm_path(struct aa_profile *profile, const char *operation,
- const char *name, int mask)
+ const char *name, int mask, uid_t uid)
{
struct aa_audit sa;
memset(&sa, 0, sizeof(sa));
sa.operation = operation;
sa.gfp_mask = GFP_KERNEL;
- sa.requested_mask = mask;
+ sa.request_mask = mask;
sa.name = name;
+ if (current->fsuid == uid)
+ sa.request_mask = mask << AA_USER_SHIFT;
+ else
+ sa.request_mask = mask << AA_OTHER_SHIFT;
- sa.denied_mask = aa_file_denied(profile, name, mask);
+ sa.denied_mask = aa_file_denied(profile, name, sa.request_mask) ;
sa.error_code = sa.denied_mask ? -EACCES : 0;
return aa_audit(profile, &sa);
@@ -672,9 +723,10 @@ int aa_link(struct aa_profile *profile,
}
if (sa.name && sa.name2) {
- sa.requested_mask = AA_MAY_LINK;
+ sa.request_mask = AA_MAY_LINK;
sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2,
- &sa.requested_mask);
+ aa_inode_mode(target->d_inode),
+ &sa.request_mask);
sa.error_code = sa.denied_mask ? -EACCES : 0;
}
@@ -818,7 +870,7 @@ aa_register_find(struct aa_profile *prof
__FUNCTION__, new_profile->name);
} else if (mandatory && profile) {
sa->info = "mandatory profile missing";
- sa->denied_mask = MAY_EXEC;
+ sa->denied_mask = sa->request_mask; /* shifted MAY_EXEC */
if (complain) {
aa_audit_hint(profile, sa);
new_profile =
@@ -829,7 +881,7 @@ aa_register_find(struct aa_profile *prof
}
} else {
/* Only way we can get into this code is if task
- * is unconfined.
+ * is unconfined, or pix.
*/
AA_DEBUG("%s: No profile found for exec image '%s'\n",
__FUNCTION__,
@@ -851,7 +903,7 @@ int aa_register(struct linux_binprm *bpr
char *buffer = NULL;
struct file *filp = bprm->file;
struct aa_profile *profile, *old_profile, *new_profile = NULL;
- int exec_mode = AA_EXEC_UNSAFE, complain = 0;
+ int exec_mode, complain = 0, shift;
struct aa_audit sa;
AA_DEBUG("%s\n", __FUNCTION__);
@@ -862,11 +914,14 @@ int aa_register(struct linux_binprm *bpr
return -ENOENT;
}
+ shift = aa_inode_mode(filp->f_dentry->d_inode);
+ exec_mode = AA_EXEC_UNSAFE << shift;
+
memset(&sa, 0, sizeof(sa));
sa.operation = "exec";
sa.gfp_mask = GFP_KERNEL;
sa.name = filename;
- sa.requested_mask = MAY_EXEC;
+ sa.request_mask = MAY_EXEC << shift;
repeat:
profile = aa_get_profile(current);
@@ -878,16 +933,16 @@ repeat:
*/
exec_mode = aa_match(profile->file_rules, filename);
- if (exec_mode & (MAY_EXEC | AA_EXEC_MODIFIERS)) {
- switch (exec_mode & (MAY_EXEC | AA_EXEC_MODIFIERS)) {
- case MAY_EXEC | AA_EXEC_INHERIT:
+ if (exec_mode & sa.request_mask) {
+ switch ((exec_mode >> shift) & AA_EXEC_MODIFIERS) {
+ case AA_EXEC_INHERIT:
AA_DEBUG("%s: INHERIT %s\n",
__FUNCTION__,
filename);
/* nothing to be done here */
goto cleanup;
- case MAY_EXEC | AA_EXEC_UNCONFINED:
+ case AA_EXEC_UNCONFINED:
AA_DEBUG("%s: UNCONFINED %s\n",
__FUNCTION__,
filename);
@@ -896,7 +951,7 @@ repeat:
new_profile = NULL;
break;
- case MAY_EXEC | AA_EXEC_PROFILE:
+ case AA_EXEC_PROFILE:
AA_DEBUG("%s: PROFILE %s\n",
__FUNCTION__,
filename);
@@ -905,6 +960,18 @@ repeat:
1, complain,
&sa);
break;
+ case AA_EXEC_PIX:
+ AA_DEBUG("%s: PROFILE %s\n",
+ __FUNCTION__,
+ filename);
+ new_profile = aa_register_find(profile,
+ filename,
+ 0, complain,
+ &sa);
+ if (!new_profile)
+ /* inherit - nothing to be done here */
+ goto cleanup;
+ break;
}
} else if (complain) {
@@ -914,9 +981,9 @@ repeat:
*/
new_profile =
aa_dup_profile(profile->ns->null_complain_profile);
- exec_mode |= AA_EXEC_UNSAFE;
+ exec_mode |= AA_EXEC_UNSAFE << shift;
} else {
- sa.denied_mask = MAY_EXEC;
+ sa.denied_mask = sa.request_mask;
aa_audit_reject(profile, &sa);
new_profile = ERR_PTR(-EPERM);
}
@@ -937,7 +1004,7 @@ repeat:
if (PTR_ERR(old_profile) == -ESTALE)
goto repeat;
if (PTR_ERR(old_profile) == -EPERM) {
- sa.denied_mask = MAY_EXEC;
+ sa.denied_mask = sa.request_mask;
sa.info = "unable to set profile due to ptrace";
sa.task = current->parent->pid;
aa_audit_reject(profile, &sa);
@@ -957,7 +1024,7 @@ repeat:
* Cases 2 and 3 are marked as requiring secure exec
* (unless policy specified "unsafe exec")
*/
- if (!(exec_mode & AA_EXEC_UNSAFE)) {
+ if (!(exec_mode & (AA_EXEC_UNSAFE << shift))) {
unsigned long bprm_flags;
bprm_flags = AA_SECURE_EXEC_NEEDED;
@@ -967,7 +1034,7 @@ repeat:
if (complain && new_profile &&
new_profile == new_profile->ns->null_complain_profile) {
- sa.requested_mask = 0;
+ sa.request_mask = 0;
sa.name = NULL;
sa.info = "set profile";
aa_audit_hint(new_profile, &sa);
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -175,14 +175,8 @@ int verify_dfa(struct aa_dfa *dfa)
for (i = 0; i < state_count; i++) {
int mode = ACCEPT_TABLE(dfa)[i];
- if (mode & ~AA_VALID_PERM_MASK)
+ if (mode & ~AA_VALID_PERM_MASK) {
goto out;
-
- /* if MAY_EXEC, exactly one exec modifier must be set */
- if (mode & MAY_EXEC) {
- mode &= AA_EXEC_MODIFIERS;
- if (mode & (mode - 1))
- goto out;
}
}
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -349,7 +349,8 @@ fail:
sa.operation = operation;
sa.gfp_mask = GFP_KERNEL;
sa.name = profile && profile->name ? profile->name : "unknown";
- sa.info = "failed to unpack profile";
+ if (!sa.info)
+ sa.info = "failed to unpack profile";
aa_audit_status(NULL, &sa);
if (profile)

View file

@ -13,7 +13,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1508,6 +1508,8 @@ static inline int may_create(struct inod
@@ -1515,6 +1515,8 @@ static inline int may_create(struct inod
return -EEXIST;
if (IS_DEADDIR(dir))
return -ENOENT;

View file

@ -1,129 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Filter out disconnected paths from /proc/mounts
Use d_path() instead of seq_path when generating /proc/mounts and
/proc/$id/mountstats, reuse the same buffer for all mounts, and filter out
disconnected paths.
This path has no net effect in itself because d_path() so far doesn't
distinguish sconnected and disconnected paths yet. The next patch fixes that
though; without this patch, the next patch would break /proc/mounts and
/proc/$id/mountstats.
There is some disagreement what /proc/mounts should include. Currently it
reports all mounts from the current namespace and doesn't include lazy
unmounts. This leads to ambiguities with the rootfs (which is an internal mount
irrelevant to user-space except in the initrd), and in chroots.
With this and the next patch, /proc/mounts only reports the mounts reachable
for the current process, which makes a lot more sense IMO. If the current
process is rooted in the namespace root (which it usually is), it will see all
mounts except for the rootfs.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/namespace.c | 23 +++++++++++++++++++++--
fs/proc/base.c | 10 +++++++++-
2 files changed, 30 insertions(+), 3 deletions(-)
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -348,8 +348,16 @@ static inline void mangle(struct seq_fil
seq_escape(m, s, " \t\n\\");
}
+/* Keep in sync with fs/proc/base.c! */
+struct proc_mounts {
+ struct seq_file m;
+ void *page;
+ int event;
+};
+
static int show_vfsmnt(struct seq_file *m, void *v)
{
+ void *page = container_of(m, struct proc_mounts, m)->page;
struct vfsmount *mnt = v;
int err = 0;
static struct proc_fs_info {
@@ -371,10 +379,15 @@ static int show_vfsmnt(struct seq_file *
{ 0, NULL }
};
struct proc_fs_info *fs_infop;
+ char *path;
+
+ path = d_path(mnt->mnt_root, mnt, page, PAGE_SIZE);
+ if (IS_ERR(path) || *path != '/')
+ return err;
mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
seq_putc(m, ' ');
- seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
+ mangle(m, path);
seq_putc(m, ' ');
mangle(m, mnt->mnt_sb->s_type->name);
seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
@@ -401,8 +414,14 @@ struct seq_operations mounts_op = {
static int show_vfsstat(struct seq_file *m, void *v)
{
+ void *page = container_of(m, struct proc_mounts, m)->page;
struct vfsmount *mnt = v;
int err = 0;
+ char *path;
+
+ path = d_path(mnt->mnt_root, mnt, page, PAGE_SIZE);
+ if (IS_ERR(path) || *path != '/')
+ return err; /* error or path unreachable from chroot */
/* device */
if (mnt->mnt_devname) {
@@ -413,7 +432,7 @@ static int show_vfsstat(struct seq_file
/* mount point */
seq_puts(m, " mounted on ");
- seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
+ mangle(m, path);
seq_putc(m, ' ');
/* file system type */
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -354,8 +354,11 @@ static const struct inode_operations pro
};
extern struct seq_operations mounts_op;
+
+/* Keep in sync with fs/namespace.c! */
struct proc_mounts {
struct seq_file m;
+ void *page;
int event;
};
@@ -383,12 +386,16 @@ static int __mounts_open(struct inode *i
p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
if (p) {
file->private_data = &p->m;
- ret = seq_open(file, seq_ops);
+ p->page = (void *)__get_free_page(GFP_KERNEL);
+ if (p->page)
+ ret = seq_open(file, seq_ops);
if (!ret) {
p->m.private = ns;
p->event = ns->event;
return 0;
}
+ if (p->page)
+ free_page((unsigned long)p->page);
kfree(p);
}
put_mnt_ns(ns);
@@ -407,6 +414,7 @@ static int mounts_release(struct inode *
container_of(file->private_data, struct proc_mounts, m);
struct mnt_namespace *ns = p->m.private;
+ free_page((unsigned long)p->page);
put_mnt_ns(ns);
return seq_release(inode, file);
}

View file

@ -1,98 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Remove duplicate proc code
Remove some duplicate code in generating the contents of /proc/mounts and
/proc/$pid/mountstats.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
This patch is optional, and does not affect the rest of this series.
fs/proc/base.c | 45 +++++++++++++++------------------------------
1 file changed, 15 insertions(+), 30 deletions(-)
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -359,7 +359,8 @@ struct proc_mounts {
int event;
};
-static int mounts_open(struct inode *inode, struct file *file)
+static int __mounts_open(struct inode *inode, struct file *file,
+ struct seq_operations *seq_ops)
{
struct task_struct *task = get_proc_task(inode);
struct mnt_namespace *ns = NULL;
@@ -382,7 +383,7 @@ static int mounts_open(struct inode *ino
p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
if (p) {
file->private_data = &p->m;
- ret = seq_open(file, &mounts_op);
+ ret = seq_open(file, seq_ops);
if (!ret) {
p->m.private = ns;
p->event = ns->event;
@@ -395,17 +396,25 @@ static int mounts_open(struct inode *ino
return ret;
}
+static int mounts_open(struct inode *inode, struct file *file)
+{
+ return __mounts_open(inode, file, &mounts_op);
+}
+
static int mounts_release(struct inode *inode, struct file *file)
{
- struct seq_file *m = file->private_data;
- struct mnt_namespace *ns = m->private;
+ struct proc_mounts *p =
+ container_of(file->private_data, struct proc_mounts, m);
+ struct mnt_namespace *ns = p->m.private;
+
put_mnt_ns(ns);
return seq_release(inode, file);
}
static unsigned mounts_poll(struct file *file, poll_table *wait)
{
- struct proc_mounts *p = file->private_data;
+ struct proc_mounts *p =
+ container_of(file->private_data, struct proc_mounts, m);
struct mnt_namespace *ns = p->m.private;
unsigned res = 0;
@@ -432,31 +441,7 @@ static const struct file_operations proc
extern struct seq_operations mountstats_op;
static int mountstats_open(struct inode *inode, struct file *file)
{
- int ret = seq_open(file, &mountstats_op);
-
- if (!ret) {
- struct seq_file *m = file->private_data;
- struct mnt_namespace *mnt_ns = NULL;
- struct task_struct *task = get_proc_task(inode);
-
- if (task) {
- task_lock(task);
- if (task->nsproxy)
- mnt_ns = task->nsproxy->mnt_ns;
- if (mnt_ns)
- get_mnt_ns(mnt_ns);
- task_unlock(task);
- put_task_struct(task);
- }
-
- if (mnt_ns)
- m->private = mnt_ns;
- else {
- seq_release(inode, file);
- ret = -EINVAL;
- }
- }
- return ret;
+ return __mounts_open(inode, file, &mountstats_op);
}
static const struct file_operations proc_mountstats_operations = {

File diff suppressed because it is too large Load diff

View file

@ -10,18 +10,29 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/fuse/file.c | 2 +-
fs/ntfs/file.c | 2 +-
fs/splice.c | 4 ++--
fs/xfs/linux-2.6/xfs_lrw.c | 2 +-
include/linux/fs.h | 4 ++--
include/linux/fs.h | 2 +-
mm/filemap.c | 16 ++++++++--------
mm/filemap_xip.c | 2 +-
mm/shmem.c | 2 +-
7 files changed, 16 insertions(+), 16 deletions(-)
7 files changed, 15 insertions(+), 15 deletions(-)
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -893,7 +893,7 @@ static ssize_t fuse_file_aio_write(struc
if (count == 0)
goto out;
- err = remove_suid(file->f_path.dentry);
+ err = remove_suid(&file->f_path);
if (err)
goto out;
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2120,7 +2120,7 @@ static ssize_t ntfs_file_aio_write_noloc
@@ -2118,7 +2118,7 @@ static ssize_t ntfs_file_aio_write_noloc
goto out;
if (!count)
goto out;
@ -32,7 +43,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
file_update_time(file);
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -775,7 +775,7 @@ generic_file_splice_write_nolock(struct
@@ -763,7 +763,7 @@ generic_file_splice_write_nolock(struct
ssize_t ret;
int err;
@ -41,18 +52,18 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (unlikely(err))
return err;
@@ -835,7 +835,7 @@ generic_file_splice_write(struct pipe_in
if (killpriv)
err = security_inode_killpriv(out->f_path.dentry);
if (!err && killsuid)
- err = __remove_suid(out->f_path.dentry, killsuid);
+ err = __remove_suid(&out->f_path, killsuid);
mutex_unlock(&inode->i_mutex);
if (err)
return err;
@@ -821,7 +821,7 @@ generic_file_splice_write(struct pipe_in
ssize_t ret;
inode_double_lock(inode, pipe->inode);
- ret = remove_suid(out->f_path.dentry);
+ ret = remove_suid(&out->f_path);
if (likely(!ret))
ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
inode_double_unlock(inode, pipe->inode);
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -727,7 +727,7 @@ start:
@@ -711,7 +711,7 @@ start:
!capable(CAP_FSETID)) {
error = xfs_write_clear_setuid(xip);
if (likely(!error))
@ -63,12 +74,9 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1766,9 +1766,9 @@ extern void __iget(struct inode * inode)
extern void clear_inode(struct inode *);
@@ -1815,7 +1815,7 @@ extern void clear_inode(struct inode *);
extern void destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *);
-extern int __remove_suid(struct dentry *, int);
+extern int __remove_suid(struct path *, int);
extern int should_remove_suid(struct dentry *);
-extern int remove_suid(struct dentry *);
+extern int remove_suid(struct path *);
@ -77,12 +85,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
extern void remove_inode_hash(struct inode *);
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1610,26 +1610,26 @@ int should_remove_suid(struct dentry *de
@@ -1660,26 +1660,26 @@ int should_remove_suid(struct dentry *de
}
EXPORT_SYMBOL(should_remove_suid);
-int __remove_suid(struct dentry *dentry, int kill)
+int __remove_suid(struct path *path, int kill)
-static int __remove_suid(struct dentry *dentry, int kill)
+static int __remove_suid(struct path *path, int kill)
{
struct iattr newattrs;
@ -111,7 +119,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
return error;
}
@@ -2342,7 +2342,7 @@ __generic_file_aio_write_nolock(struct k
@@ -2394,7 +2394,7 @@ __generic_file_aio_write_nolock(struct k
if (count == 0)
goto out;
@ -122,7 +130,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -378,7 +378,7 @@ xip_file_write(struct file *filp, const
@@ -380,7 +380,7 @@ xip_file_write(struct file *filp, const
if (count == 0)
goto out_backing;
@ -131,14 +139,3 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (ret)
goto out_backing;
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1525,7 +1525,7 @@ shmem_file_write(struct file *file, cons
if (err || !count)
goto out;
- err = remove_suid(file->f_path.dentry);
+ err = remove_suid(&file->f_path);
if (err)
goto out;

View file

@ -15,20 +15,20 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
security/selinux/hooks.c | 3 ++-
5 files changed, 13 insertions(+), 8 deletions(-)
--- a/fs/namei.c 2007-11-02 17:44:43.000000000 -0400
+++ b/fs/namei.c 2007-11-02 17:49:23.000000000 -0400
@@ -1583,7 +1583,7 @@ int vfs_create(struct inode *dir, struct
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1590,7 +1590,7 @@ int vfs_create(struct inode *dir, struct
return -EACCES; /* shouldn't it be ENOSYS? */
mode &= S_IALLUGO;
mode |= S_IFREG;
- error = security_inode_create(dir, dentry, mode);
+ error = security_inode_create(dir, dentry, nd ? nd->mnt : NULL, mode);
+ error = security_inode_create(dir, dentry, nd ? nd->path.mnt : NULL, mode);
if (error)
return error;
DQUOT_INIT(dir);
--- a/include/linux/security.h 2007-11-02 17:44:43.000000000 -0400
+++ b/include/linux/security.h 2007-11-02 17:49:39.000000000 -0400
@@ -297,6 +297,7 @@ struct request_sock;
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -341,6 +341,7 @@ static inline void security_free_mnt_opt
* 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.
@ -36,7 +36,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* @mode contains the file mode of the file to be created.
* Return 0 if permission is granted.
* @inode_link:
@@ -1247,8 +1248,8 @@ struct security_operations {
@@ -1355,8 +1356,8 @@ struct security_operations {
void (*inode_free_security) (struct inode *inode);
int (*inode_init_security) (struct inode *inode, struct inode *dir,
char **name, void **value, size_t *len);
@ -47,7 +47,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int (*inode_link) (struct dentry *old_dentry,
struct inode *dir, struct dentry *new_dentry);
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
@@ -1503,7 +1504,8 @@ int security_inode_alloc(struct inode *i
@@ -1628,7 +1629,8 @@ int security_inode_alloc(struct inode *i
void security_inode_free(struct inode *inode);
int security_inode_init_security(struct inode *inode, struct inode *dir,
char **name, void **value, size_t *len);
@ -57,7 +57,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
@@ -1813,6 +1815,7 @@ static inline int security_inode_init_se
@@ -1968,6 +1970,7 @@ static inline int security_inode_init_se
static inline int security_inode_create(struct inode *dir,
struct dentry *dentry,
@ -65,9 +65,9 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int mode)
{
return 0;
--- a/security/dummy.c 2007-11-02 17:44:43.000000000 -0400
+++ b/security/dummy.c 2007-11-02 17:49:23.000000000 -0400
@@ -262,7 +262,7 @@ static int dummy_inode_init_security (st
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -289,7 +289,7 @@ static int dummy_inode_init_security (st
}
static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
@ -76,9 +76,9 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
{
return 0;
}
--- a/security/security.c 2007-11-02 17:46:44.000000000 -0400
+++ b/security/security.c 2007-11-02 17:49:23.000000000 -0400
@@ -329,11 +329,12 @@ int security_inode_init_security(struct
--- a/security/security.c
+++ b/security/security.c
@@ -388,11 +388,12 @@ int security_inode_init_security(struct
}
EXPORT_SYMBOL(security_inode_init_security);
@ -93,9 +93,9 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
--- a/security/selinux/hooks.c 2007-11-02 17:44:43.000000000 -0400
+++ b/security/selinux/hooks.c 2007-11-02 17:49:23.000000000 -0400
@@ -2184,7 +2184,8 @@ static int selinux_inode_init_security(s
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2507,7 +2507,8 @@ static int selinux_inode_init_security(s
return 0;
}

View file

@ -17,7 +17,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -115,7 +115,7 @@ vfs_getxattr(struct dentry *dentry, stru
@@ -141,7 +141,7 @@ vfs_getxattr(struct dentry *dentry, stru
if (error)
return error;
@ -28,7 +28,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -405,7 +405,7 @@ struct request_sock;
@@ -450,7 +450,7 @@ static inline void security_free_mnt_opt
* @value identified by @name for @dentry and @mnt.
* @inode_getxattr:
* Check permission before obtaining the extended attributes
@ -37,57 +37,57 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* Return 0 if permission is granted.
* @inode_listxattr:
* Check permission before obtaining the list of extended attribute
@@ -1291,7 +1291,8 @@ struct security_operations {
@@ -1401,7 +1401,8 @@ struct security_operations {
struct vfsmount *mnt,
char *name, void *value,
const char *name, const void *value,
size_t size, int flags);
- int (*inode_getxattr) (struct dentry *dentry, char *name);
- int (*inode_getxattr) (struct dentry *dentry, const char *name);
+ int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
+ const char *name);
int (*inode_listxattr) (struct dentry *dentry);
int (*inode_removexattr) (struct dentry *dentry, char *name);
int (*inode_removexattr) (struct dentry *dentry, const char *name);
int (*inode_need_killpriv) (struct dentry *dentry);
@@ -1554,7 +1555,8 @@ int security_inode_setxattr(struct dentr
@@ -1682,7 +1683,8 @@ int security_inode_setxattr(struct dentr
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
int flags);
-int security_inode_getxattr(struct dentry *dentry, char *name);
const char *name, const void *value,
size_t size, int flags);
-int security_inode_getxattr(struct dentry *dentry, const char *name);
+int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
+ const char *name);
int security_inode_listxattr(struct dentry *dentry);
int security_inode_removexattr(struct dentry *dentry, char *name);
int security_inode_removexattr(struct dentry *dentry, const char *name);
int security_inode_need_killpriv(struct dentry *dentry);
@@ -1954,7 +1956,8 @@ static inline void security_inode_post_s
int flags)
@@ -2114,7 +2116,8 @@ static inline void security_inode_post_s
{ }
-static inline int security_inode_getxattr (struct dentry *dentry, char *name)
+static inline int security_inode_getxattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name)
static inline int security_inode_getxattr(struct dentry *dentry,
- const char *name)
+ struct vfsmount *mnt,
+ const char *name)
{
return 0;
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -365,7 +365,8 @@ static void dummy_inode_post_setxattr (s
@@ -392,7 +392,8 @@ static void dummy_inode_post_setxattr (s
{
}
-static int dummy_inode_getxattr (struct dentry *dentry, char *name)
+static int dummy_inode_getxattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name)
-static int dummy_inode_getxattr (struct dentry *dentry, const char *name)
+static int dummy_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt,
+ const char *name)
{
return 0;
}
--- a/security/security.c
+++ b/security/security.c
@@ -458,11 +458,12 @@ void security_inode_post_setxattr(struct
security_ops->inode_post_setxattr(dentry, mnt, name, value, size, flags);
@@ -520,11 +520,12 @@ void security_inode_post_setxattr(struct
flags);
}
-int security_inode_getxattr(struct dentry *dentry, char *name)
-int security_inode_getxattr(struct dentry *dentry, const char *name)
+int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
+ const char *name)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
@ -98,13 +98,13 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_listxattr(struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2409,7 +2409,8 @@ static void selinux_inode_post_setxattr(
@@ -2732,7 +2732,8 @@ static void selinux_inode_post_setxattr(
return;
}
-static int selinux_inode_getxattr (struct dentry *dentry, char *name)
-static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
+static int selinux_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
+ const char *name)
{
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}

View file

@ -9,15 +9,15 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 3 ++-
include/linux/security.h | 16 +++++++++++-----
include/linux/security.h | 18 ++++++++++++------
security/dummy.c | 6 ++++--
security/security.c | 8 +++++---
security/selinux/hooks.c | 9 +++++++--
5 files changed, 29 insertions(+), 13 deletions(-)
5 files changed, 30 insertions(+), 14 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2356,7 +2356,8 @@ int vfs_link(struct dentry *old_dentry,
@@ -2506,7 +2506,8 @@ int vfs_link(struct dentry *old_dentry,
if (S_ISDIR(old_dentry->d_inode->i_mode))
return -EPERM;
@ -29,7 +29,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -303,8 +303,10 @@ struct request_sock;
@@ -347,8 +347,10 @@ static inline void security_free_mnt_opt
* @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.
@ -40,7 +40,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* Return 0 if permission is granted.
* @inode_unlink:
* Check the permission to remove a hard link to a file.
@@ -1255,8 +1257,9 @@ struct security_operations {
@@ -1363,8 +1365,9 @@ struct security_operations {
char **name, void **value, size_t *len);
int (*inode_create) (struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
@ -52,7 +52,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, const char *old_name);
@@ -1513,8 +1516,9 @@ int security_inode_init_security(struct
@@ -1638,8 +1641,9 @@ int security_inode_init_security(struct
char **name, void **value, size_t *len);
int security_inode_create(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
@ -64,13 +64,14 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, const char *old_name);
@@ -1832,8 +1836,10 @@ static inline int security_inode_create
@@ -1987,8 +1991,10 @@ static inline int security_inode_create(
}
static inline int security_inode_link(struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
struct inode *dir,
- struct inode *dir,
- struct dentry *new_dentry)
+ struct vfsmount *old_mnt,
+ struct inode *dir,
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
{
@ -78,7 +79,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -267,8 +267,10 @@ static int dummy_inode_create (struct in
@@ -294,8 +294,10 @@ static int dummy_inode_create (struct in
return 0;
}
@ -93,7 +94,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -336,12 +336,14 @@ int security_inode_create(struct inode *
@@ -396,12 +396,14 @@ int security_inode_create(struct inode *
return security_ops->inode_create(dir, dentry, mnt, mode);
}
@ -113,7 +114,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2190,11 +2190,16 @@ static int selinux_inode_create(struct i
@@ -2513,11 +2513,16 @@ static int selinux_inode_create(struct i
return may_create(dir, dentry, SECCLASS_FILE);
}
@ -121,7 +122,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
+static int selinux_inode_link(struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
+ struct inode *dir,
+ struct dentry *new_dentry,
+ struct dentry *new_dentry
+ struct vfsmount *new_mnt)
{
int rc;

View file

@ -17,7 +17,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -148,7 +148,7 @@ vfs_listxattr(struct dentry *dentry, str
@@ -174,7 +174,7 @@ vfs_listxattr(struct dentry *dentry, str
struct inode *inode = dentry->d_inode;
ssize_t error;
@ -28,7 +28,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
error = -EOPNOTSUPP;
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -409,7 +409,7 @@ struct request_sock;
@@ -454,7 +454,7 @@ static inline void security_free_mnt_opt
* Return 0 if permission is granted.
* @inode_listxattr:
* Check permission before obtaining the list of extended attribute
@ -37,25 +37,25 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* Return 0 if permission is granted.
* @inode_removexattr:
* Check permission before removing the extended attribute
@@ -1293,7 +1293,7 @@ struct security_operations {
@@ -1403,7 +1403,7 @@ struct security_operations {
size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
char *name);
const char *name);
- int (*inode_listxattr) (struct dentry *dentry);
+ int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
int (*inode_removexattr) (struct dentry *dentry, char *name);
int (*inode_removexattr) (struct dentry *dentry, const char *name);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
@@ -1557,7 +1557,7 @@ void security_inode_post_setxattr(struct
int flags);
@@ -1685,7 +1685,7 @@ void security_inode_post_setxattr(struct
size_t size, int flags);
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name);
const char *name);
-int security_inode_listxattr(struct dentry *dentry);
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
int security_inode_removexattr(struct dentry *dentry, char *name);
int security_inode_removexattr(struct dentry *dentry, const char *name);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
@@ -1962,7 +1962,8 @@ static inline int security_inode_getxatt
@@ -2122,7 +2122,8 @@ static inline int security_inode_getxatt
return 0;
}
@ -67,7 +67,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -371,7 +371,7 @@ static int dummy_inode_getxattr (struct
@@ -398,7 +398,7 @@ static int dummy_inode_getxattr (struct
return 0;
}
@ -78,7 +78,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -466,11 +466,11 @@ int security_inode_getxattr(struct dentr
@@ -528,11 +528,11 @@ int security_inode_getxattr(struct dentr
return security_ops->inode_getxattr(dentry, mnt, name);
}
@ -91,10 +91,10 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
+ return security_ops->inode_listxattr(dentry, mnt);
}
int security_inode_removexattr(struct dentry *dentry, char *name)
int security_inode_removexattr(struct dentry *dentry, const char *name)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2415,7 +2415,7 @@ static int selinux_inode_getxattr (struc
@@ -2738,7 +2738,7 @@ static int selinux_inode_getxattr(struct
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}

View file

@ -17,7 +17,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2009,7 +2009,7 @@ int vfs_mkdir(struct inode *dir, struct
@@ -2139,7 +2139,7 @@ int vfs_mkdir(struct inode *dir, struct
return -EPERM;
mode &= (S_IRWXUGO|S_ISVTX);
@ -28,7 +28,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -322,6 +322,7 @@ struct request_sock;
@@ -366,6 +366,7 @@ static inline void security_free_mnt_opt
* associated with inode strcture @dir.
* @dir containst the inode structure of parent of the directory to be created.
* @dentry contains the dentry structure of new directory.
@ -36,7 +36,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* @mode contains the mode of new directory.
* Return 0 if permission is granted.
* @inode_rmdir:
@@ -1256,7 +1257,8 @@ struct security_operations {
@@ -1364,7 +1365,8 @@ struct security_operations {
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
int (*inode_symlink) (struct inode *dir,
struct dentry *dentry, const char *old_name);
@ -46,7 +46,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
int mode, dev_t dev);
@@ -1513,7 +1515,8 @@ int security_inode_link(struct dentry *o
@@ -1638,7 +1640,8 @@ int security_inode_link(struct dentry *o
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
const char *old_name);
@ -56,7 +56,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -1846,6 +1849,7 @@ static inline int security_inode_symlink
@@ -2001,6 +2004,7 @@ static inline int security_inode_symlink
static inline int security_inode_mkdir(struct inode *dir,
struct dentry *dentry,
@ -66,7 +66,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -285,7 +285,7 @@ static int dummy_inode_symlink (struct i
@@ -312,7 +312,7 @@ static int dummy_inode_symlink (struct i
}
static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry,
@ -77,7 +77,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -359,11 +359,12 @@ int security_inode_symlink(struct inode
@@ -419,11 +419,12 @@ int security_inode_symlink(struct inode
return security_ops->inode_symlink(dir, dentry, old_name);
}
@ -94,7 +94,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2215,7 +2215,8 @@ static int selinux_inode_symlink(struct
@@ -2538,7 +2538,8 @@ static int selinux_inode_symlink(struct
return may_create(dir, dentry, SECCLASS_LNK_FILE);
}

View file

@ -8,27 +8,41 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
fs/namei.c | 6 +++---
include/linux/security.h | 7 +++++--
security/dummy.c | 2 +-
security/security.c | 5 +++--
security/selinux/hooks.c | 5 +++--
5 files changed, 13 insertions(+), 8 deletions(-)
5 files changed, 15 insertions(+), 10 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1932,7 +1932,7 @@ int vfs_mknod(struct inode *dir, struct
if (!dir->i_op || !dir->i_op->mknod)
return -EPERM;
@@ -2041,7 +2041,7 @@ int vfs_mknod(struct inode *dir, struct
if (error)
return error;
- error = security_inode_mknod(dir, dentry, mode, dev);
+ error = security_inode_mknod(dir, dentry, mnt, mode, dev);
if (error)
return error;
@@ -2105,11 +2105,11 @@ asmlinkage long sys_mknodat(int dfd, con
break;
case S_IFCHR: case S_IFBLK:
error = vfs_mknod(nd.path.dentry->d_inode, dentry,
- nd.path, mode, new_decode_dev(dev));
+ nd.path.mnt, mode, new_decode_dev(dev));
break;
case S_IFIFO: case S_IFSOCK:
error = vfs_mknod(nd.path.dentry->d_inode, dentry,
- nd.path, mode, 0);
+ nd.path.mnt, mode, 0);
break;
}
mnt_drop_write(nd.path.mnt);
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -337,6 +337,7 @@ struct request_sock;
@@ -381,6 +381,7 @@ static inline void security_free_mnt_opt
* and not this hook.
* @dir contains the inode structure of parent of the new file.
* @dentry contains the dentry structure of the new file.
@ -36,7 +50,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* @mode contains the mode of the new file.
* @dev contains the device number.
* Return 0 if permission is granted.
@@ -1261,7 +1262,7 @@ struct security_operations {
@@ -1369,7 +1370,7 @@ struct security_operations {
struct vfsmount *mnt, int mode);
int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
@ -45,7 +59,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
int (*inode_readlink) (struct dentry *dentry);
@@ -1518,7 +1519,8 @@ int security_inode_symlink(struct inode
@@ -1643,7 +1644,8 @@ int security_inode_symlink(struct inode
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
@ -55,7 +69,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
int security_inode_readlink(struct dentry *dentry);
@@ -1863,6 +1865,7 @@ static inline int security_inode_rmdir (
@@ -2018,6 +2020,7 @@ static inline int security_inode_rmdir(s
static inline int security_inode_mknod(struct inode *dir,
struct dentry *dentry,
@ -65,7 +79,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -296,7 +296,7 @@ static int dummy_inode_rmdir (struct ino
@@ -323,7 +323,7 @@ static int dummy_inode_rmdir (struct ino
}
static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry,
@ -76,7 +90,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -374,11 +374,12 @@ int security_inode_rmdir(struct inode *d
@@ -434,11 +434,12 @@ int security_inode_rmdir(struct inode *d
return security_ops->inode_rmdir(dir, dentry);
}
@ -93,7 +107,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2226,11 +2226,12 @@ static int selinux_inode_rmdir(struct in
@@ -2549,11 +2549,12 @@ static int selinux_inode_rmdir(struct in
return may_link(dir, dentry, MAY_RMDIR);
}

View file

@ -21,14 +21,14 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
error = -EINVAL;
if (inode->i_op && inode->i_op->readlink) {
- error = security_inode_readlink(nd.dentry);
+ error = security_inode_readlink(nd.dentry, nd.mnt);
- error = security_inode_readlink(nd.path.dentry);
+ error = security_inode_readlink(nd.path.dentry, nd.path.mnt);
if (!error) {
touch_atime(nd.mnt, nd.dentry);
error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
touch_atime(nd.path.mnt, nd.path.dentry);
error = inode->i_op->readlink(nd.path.dentry,
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -352,6 +352,7 @@ struct request_sock;
@@ -396,6 +396,7 @@ static inline void security_free_mnt_opt
* @inode_readlink:
* Check the permission to read the symbolic link.
* @dentry contains the dentry structure for the file link.
@ -36,7 +36,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* Return 0 if permission is granted.
* @inode_follow_link:
* Check permission to follow a symbolic link when looking up a pathname.
@@ -1266,7 +1267,7 @@ struct security_operations {
@@ -1374,7 +1375,7 @@ struct security_operations {
struct vfsmount *mnt, int mode, dev_t dev);
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
@ -45,7 +45,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
int (*inode_setattr) (struct dentry *dentry, struct vfsmount *mnt,
@@ -1524,7 +1525,7 @@ int security_inode_mknod(struct inode *d
@@ -1649,7 +1650,7 @@ int security_inode_mknod(struct inode *d
struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
@ -54,7 +54,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
@@ -1881,7 +1882,8 @@ static inline int security_inode_rename
@@ -2036,7 +2037,8 @@ static inline int security_inode_rename(
return 0;
}
@ -66,7 +66,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -309,7 +309,7 @@ static int dummy_inode_rename (struct in
@@ -336,7 +336,7 @@ static int dummy_inode_rename (struct in
return 0;
}
@ -77,7 +77,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -392,11 +392,11 @@ int security_inode_rename(struct inode *
@@ -452,11 +452,11 @@ int security_inode_rename(struct inode *
new_dir, new_dentry);
}
@ -93,7 +93,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2245,7 +2245,7 @@ static int selinux_inode_rename(struct i
@@ -2568,7 +2568,7 @@ static int selinux_inode_rename(struct i
return may_rename(old_inode, old_dentry, new_inode, new_dentry);
}

View file

@ -9,16 +9,16 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 2 +-
include/linux/security.h | 13 ++++++++-----
include/linux/security.h | 14 +++++++++-----
security/commoncap.c | 3 ++-
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
6 files changed, 18 insertions(+), 11 deletions(-)
6 files changed, 19 insertions(+), 11 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -176,7 +176,7 @@ vfs_removexattr(struct dentry *dentry, s
@@ -202,7 +202,7 @@ vfs_removexattr(struct dentry *dentry, s
if (error)
return error;
@ -29,42 +29,43 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -57,7 +57,7 @@ extern int cap_bprm_set_security (struct
extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, char *name);
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name);
@@ -56,7 +56,8 @@ extern int cap_bprm_secureexec(struct li
extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
const char *name, const void *value, size_t size,
int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ const char *name);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
@@ -1294,7 +1294,8 @@ struct security_operations {
@@ -1404,7 +1405,8 @@ struct security_operations {
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
char *name);
const char *name);
int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
- int (*inode_removexattr) (struct dentry *dentry, char *name);
- int (*inode_removexattr) (struct dentry *dentry, const char *name);
+ int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
+ const char *name);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
@@ -1558,7 +1559,8 @@ void security_inode_post_setxattr(struct
int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -1686,7 +1688,8 @@ void security_inode_post_setxattr(struct
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name);
const char *name);
int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
-int security_inode_removexattr(struct dentry *dentry, char *name);
-int security_inode_removexattr(struct dentry *dentry, const char *name);
+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
+ const char *name);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
@@ -1968,9 +1970,10 @@ static inline int security_inode_listxat
return 0;
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -2129,9 +2132,10 @@ static inline int security_inode_listxat
}
-static inline int security_inode_removexattr (struct dentry *dentry, char *name)
+static inline int security_inode_removexattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name)
static inline int security_inode_removexattr(struct dentry *dentry,
- const char *name)
+ struct vfsmount *mnt,
+ const char *name)
{
- return cap_inode_removexattr(dentry, name);
+ return cap_inode_removexattr(dentry, mnt, name);
@ -73,37 +74,37 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
static inline int security_inode_need_killpriv(struct dentry *dentry)
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -382,7 +382,8 @@ int cap_inode_setxattr(struct dentry *de
@@ -398,7 +398,8 @@ int cap_inode_setxattr(struct dentry *de
return 0;
}
-int cap_inode_removexattr(struct dentry *dentry, char *name)
-int cap_inode_removexattr(struct dentry *dentry, const char *name)
+int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
+ const char *name)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -376,7 +376,8 @@ static int dummy_inode_listxattr (struct
@@ -403,7 +403,8 @@ static int dummy_inode_listxattr (struct
return 0;
}
-static int dummy_inode_removexattr (struct dentry *dentry, char *name)
-static int dummy_inode_removexattr (struct dentry *dentry, const char *name)
+static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
+ const char *name)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
--- a/security/security.c
+++ b/security/security.c
@@ -473,11 +473,12 @@ int security_inode_listxattr(struct dent
@@ -535,11 +535,12 @@ int security_inode_listxattr(struct dent
return security_ops->inode_listxattr(dentry, mnt);
}
-int security_inode_removexattr(struct dentry *dentry, char *name)
-int security_inode_removexattr(struct dentry *dentry, const char *name)
+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
+ const char *name)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
@ -114,13 +115,13 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_need_killpriv(struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2420,7 +2420,8 @@ static int selinux_inode_listxattr (stru
@@ -2743,7 +2743,8 @@ static int selinux_inode_listxattr(struc
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
-static int selinux_inode_removexattr (struct dentry *dentry, char *name)
-static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
+static int selinux_inode_removexattr(struct dentry *dentry,
+ struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, const char *name)
{
if (strcmp(name, XATTR_NAME_SELINUX))
return selinux_inode_setotherxattr(dentry, name);

View file

@ -17,7 +17,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2480,7 +2480,8 @@ static int vfs_rename_dir(struct inode *
@@ -2636,7 +2636,8 @@ static int vfs_rename_dir(struct inode *
return error;
}
@ -27,7 +27,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (error)
return error;
@@ -2514,7 +2515,8 @@ static int vfs_rename_other(struct inode
@@ -2670,7 +2671,8 @@ static int vfs_rename_other(struct inode
struct inode *target;
int error;
@ -39,7 +39,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -350,8 +350,10 @@ struct request_sock;
@@ -394,8 +394,10 @@ static inline void security_free_mnt_opt
* Check for permission to rename a file or directory.
* @old_dir contains the inode structure for parent of the old link.
* @old_dentry contains the dentry structure of the old link.
@ -50,7 +50,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* Return 0 if permission is granted.
* @inode_readlink:
* Check the permission to read the symbolic link.
@@ -1273,7 +1275,9 @@ struct security_operations {
@@ -1381,7 +1383,9 @@ struct security_operations {
int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode, dev_t dev);
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
@ -61,7 +61,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt);
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
@@ -1534,7 +1538,8 @@ int security_inode_rmdir(struct inode *d
@@ -1659,7 +1663,8 @@ int security_inode_rmdir(struct inode *d
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@ -71,7 +71,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
@@ -1890,8 +1895,10 @@ static inline int security_inode_mknod (
@@ -2045,8 +2050,10 @@ static inline int security_inode_mknod(s
static inline int security_inode_rename(struct inode *old_dir,
struct dentry *old_dentry,
@ -85,7 +85,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -307,8 +307,10 @@ static int dummy_inode_mknod (struct ino
@@ -334,8 +334,10 @@ static int dummy_inode_mknod (struct ino
static int dummy_inode_rename (struct inode *old_inode,
struct dentry *old_dentry,
@ -99,7 +99,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -387,13 +387,14 @@ int security_inode_mknod(struct inode *d
@@ -447,13 +447,14 @@ int security_inode_mknod(struct inode *d
}
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@ -119,7 +119,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2246,8 +2246,12 @@ static int selinux_inode_mknod(struct in
@@ -2569,8 +2569,12 @@ static int selinux_inode_mknod(struct in
return may_create(dir, dentry, inode_mode_to_security_class(mode));
}

View file

@ -17,7 +17,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2104,7 +2104,7 @@ int vfs_rmdir(struct inode *dir, struct
@@ -2239,7 +2239,7 @@ int vfs_rmdir(struct inode *dir, struct
if (d_mountpoint(dentry))
error = -EBUSY;
else {
@ -28,7 +28,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (!error)
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -332,6 +332,7 @@ struct request_sock;
@@ -376,6 +376,7 @@ static inline void security_free_mnt_opt
* 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.
@ -36,7 +36,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* Return 0 if permission is granted.
* @inode_mknod:
* Check permissions when creating a special file (or a socket or a fifo
@@ -1265,7 +1266,8 @@ struct security_operations {
@@ -1373,7 +1374,8 @@ struct security_operations {
struct vfsmount *mnt, const char *old_name);
int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
@ -46,7 +46,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode, dev_t dev);
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
@@ -1524,7 +1526,8 @@ int security_inode_symlink(struct inode
@@ -1649,7 +1651,8 @@ int security_inode_symlink(struct inode
struct vfsmount *mnt, const char *old_name);
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
@ -56,7 +56,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -1867,7 +1870,8 @@ static inline int security_inode_mkdir (
@@ -2022,7 +2025,8 @@ static inline int security_inode_mkdir(s
}
static inline int security_inode_rmdir(struct inode *dir,
@ -68,7 +68,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -292,7 +292,8 @@ static int dummy_inode_mkdir (struct ino
@@ -319,7 +319,8 @@ static int dummy_inode_mkdir (struct ino
return 0;
}
@ -80,7 +80,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -369,11 +369,12 @@ int security_inode_mkdir(struct inode *d
@@ -429,11 +429,12 @@ int security_inode_mkdir(struct inode *d
return security_ops->inode_mkdir(dir, dentry, mnt, mode);
}
@ -97,7 +97,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2227,7 +2227,8 @@ static int selinux_inode_mkdir(struct in
@@ -2550,7 +2550,8 @@ static int selinux_inode_mkdir(struct in
return may_create(dir, dentry, SECCLASS_DIR);
}

View file

@ -9,11 +9,11 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/attr.c | 4 ++--
include/linux/security.h | 8 ++++++--
include/linux/security.h | 10 +++++++---
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 5 +++--
5 files changed, 16 insertions(+), 9 deletions(-)
5 files changed, 17 insertions(+), 10 deletions(-)
--- a/fs/attr.c
+++ b/fs/attr.c
@ -35,7 +35,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -372,6 +372,7 @@ struct request_sock;
@@ -416,6 +416,7 @@ static inline void security_free_mnt_opt
* file attributes change (such as when a file is truncated, chown/chmod
* operations, transferring disk quotas, etc).
* @dentry contains the dentry structure for the file.
@ -43,7 +43,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* @attr is the iattr structure containing the new file attributes.
* Return 0 if permission is granted.
* @inode_getattr:
@@ -1264,7 +1265,8 @@ struct security_operations {
@@ -1372,7 +1373,8 @@ struct security_operations {
int (*inode_readlink) (struct dentry *dentry);
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
@ -52,8 +52,8 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
+ struct iattr *attr);
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
void (*inode_delete) (struct inode *inode);
int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
@@ -1519,7 +1521,8 @@ int security_inode_rename(struct inode *
int (*inode_setxattr) (struct dentry *dentry, const char *name,
@@ -1644,7 +1646,8 @@ int security_inode_rename(struct inode *
int security_inode_readlink(struct dentry *dentry);
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
@ -62,18 +62,20 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
+ struct iattr *attr);
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
void security_inode_delete(struct inode *inode);
int security_inode_setxattr(struct dentry *dentry, char *name,
@@ -1887,6 +1890,7 @@ static inline int security_inode_permiss
int security_inode_setxattr(struct dentry *dentry, const char *name,
@@ -2042,7 +2045,8 @@ static inline int security_inode_permiss
}
static inline int security_inode_setattr(struct dentry *dentry,
- struct iattr *attr)
+ struct vfsmount *mnt,
struct iattr *attr)
+ struct iattr *attr)
{
return 0;
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -325,7 +325,8 @@ static int dummy_inode_permission (struc
@@ -352,7 +352,8 @@ static int dummy_inode_permission (struc
return 0;
}
@ -85,7 +87,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -411,11 +411,12 @@ int security_inode_permission(struct ino
@@ -471,11 +471,12 @@ int security_inode_permission(struct ino
return security_ops->inode_permission(inode, mask, nd);
}
@ -102,8 +104,8 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2275,11 +2275,12 @@ static int selinux_inode_permission(stru
file_mask_to_av(inode->i_mode, mask), NULL);
@@ -2598,11 +2598,12 @@ static int selinux_inode_permission(stru
open_file_mask_to_av(inode->i_mode, mask), NULL);
}
-static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)

View file

@ -9,16 +9,16 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 4 ++--
include/linux/security.h | 35 +++++++++++++++++++++--------------
security/commoncap.c | 4 ++--
security/dummy.c | 9 ++++++---
security/security.c | 14 ++++++++------
security/selinux/hooks.c | 8 ++++++--
6 files changed, 45 insertions(+), 29 deletions(-)
include/linux/security.h | 41 ++++++++++++++++++++++++++---------------
security/commoncap.c | 5 +++--
security/dummy.c | 8 +++++---
security/security.c | 16 ++++++++++------
security/selinux/hooks.c | 8 +++++---
6 files changed, 51 insertions(+), 31 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -79,7 +79,7 @@ vfs_setxattr(struct dentry *dentry, stru
@@ -78,7 +78,7 @@ vfs_setxattr(struct dentry *dentry, stru
return error;
mutex_lock(&inode->i_mutex);
@ -27,7 +27,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (error)
goto out;
error = -EOPNOTSUPP;
@@ -87,7 +87,7 @@ vfs_setxattr(struct dentry *dentry, stru
@@ -86,7 +86,7 @@ vfs_setxattr(struct dentry *dentry, stru
error = inode->i_op->setxattr(dentry, name, value, size, flags);
if (!error) {
fsnotify_xattr(dentry);
@ -38,16 +38,19 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
} else if (!strncmp(name, XATTR_SECURITY_PREFIX,
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -56,7 +56,7 @@ extern void cap_capset_set (struct task_
@@ -53,8 +53,9 @@ extern void cap_capset_set(struct task_s
extern int cap_bprm_set_security(struct linux_binprm *bprm);
extern void cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
-extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
extern int cap_inode_removexattr(struct dentry *dentry, char *name);
-extern int cap_inode_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ const char *name, const void *value, size_t size,
+ int flags);
extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
@@ -398,11 +398,11 @@ struct request_sock;
@@ -442,11 +443,11 @@ static inline void security_free_mnt_opt
* inode.
* @inode_setxattr:
* Check permission before setting the extended attributes
@ -61,108 +64,112 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* @inode_getxattr:
* Check permission before obtaining the extended attributes
* identified by @name for @dentry.
@@ -1285,9 +1285,11 @@ struct security_operations {
@@ -1393,10 +1394,13 @@ struct security_operations {
struct iattr *attr);
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
void (*inode_delete) (struct inode *inode);
- int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
- size_t size, int flags);
- void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
- int (*inode_setxattr) (struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
- void (*inode_post_setxattr) (struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
+ int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size, int flags);
+ const char *name, const void *value, size_t size,
+ int flags);
+ void (*inode_post_setxattr) (struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name, void *value,
size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, char *name);
+ const char *name, const void *value,
+ size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, const char *name);
int (*inode_listxattr) (struct dentry *dentry);
@@ -1547,10 +1549,11 @@ int security_inode_setattr(struct dentry
int (*inode_removexattr) (struct dentry *dentry, const char *name);
@@ -1672,10 +1676,12 @@ int security_inode_setattr(struct dentry
struct iattr *attr);
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
void security_inode_delete(struct inode *inode);
-int security_inode_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags);
-void security_inode_post_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags);
-int security_inode_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
-void security_inode_post_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size, int flags);
+ const char *name, const void *value,
+ size_t size, int flags);
+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags);
int security_inode_getxattr(struct dentry *dentry, char *name);
+ const char *name, const void *value,
+ size_t size, int flags);
int security_inode_getxattr(struct dentry *dentry, const char *name);
int security_inode_listxattr(struct dentry *dentry);
int security_inode_removexattr(struct dentry *dentry, char *name);
@@ -1937,14 +1940,18 @@ static inline int security_inode_getattr
static inline void security_inode_delete (struct inode *inode)
int security_inode_removexattr(struct dentry *dentry, const char *name);
@@ -2093,13 +2099,18 @@ static inline void security_inode_delete
{ }
-static inline int security_inode_setxattr (struct dentry *dentry, char *name,
+static inline int security_inode_setxattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name,
void *value, size_t size, int flags)
static inline int security_inode_setxattr(struct dentry *dentry,
- const char *name, const void *value, size_t size, int flags)
+ struct vfsmount *mnt,
+ const char *name, const void *value,
+ size_t size, int flags)
{
- return cap_inode_setxattr(dentry, name, value, size, flags);
+ return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
}
-static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
+static inline void security_inode_post_setxattr (struct dentry *dentry,
static inline void security_inode_post_setxattr(struct dentry *dentry,
- const char *name, const void *value, size_t size, int flags)
+ struct vfsmount *mnt,
+ char *name,
+ void *value, size_t size,
+ int flags)
+ const char *name,
+ const void *value,
+ size_t size, int flags)
{ }
static inline int security_inode_getxattr (struct dentry *dentry, char *name)
static inline int security_inode_getxattr(struct dentry *dentry,
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -368,8 +368,8 @@ int cap_bprm_secureexec (struct linux_bi
@@ -383,8 +383,9 @@ int cap_bprm_secureexec (struct linux_bi
current->egid != current->gid);
}
-int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
- size_t size, int flags)
+int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
+ void *value, size_t size, int flags)
-int cap_inode_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ const char *name, const void *value, size_t size,
+ int flags)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -347,8 +347,9 @@ static void dummy_inode_delete (struct i
@@ -374,8 +374,9 @@ static void dummy_inode_delete (struct i
return;
}
-static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
- size_t size, int flags)
-static int dummy_inode_setxattr (struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags)
+ const char *name, const void *value,
+ size_t size, int flags)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -357,7 +358,9 @@ static int dummy_inode_setxattr (struct
@@ -384,7 +385,8 @@ static int dummy_inode_setxattr (struct
return 0;
}
-static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
-static void dummy_inode_post_setxattr (struct dentry *dentry, const char *name,
+static void dummy_inode_post_setxattr (struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name, void *value,
size_t size, int flags)
+ struct vfsmount *mnt, const char *name,
const void *value, size_t size,
int flags)
{
}
--- a/security/security.c
+++ b/security/security.c
@@ -440,20 +440,22 @@ void security_inode_delete(struct inode
@@ -500,20 +500,24 @@ void security_inode_delete(struct inode
security_ops->inode_delete(inode);
}
-int security_inode_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
-int security_inode_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size, int flags)
+ const char *name, const void *value, size_t size,
+ int flags)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
@ -171,40 +178,41 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
+ flags);
}
-void security_inode_post_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
-void security_inode_post_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags)
+ const char *name, const void *value,
+ size_t size, int flags)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return;
- security_ops->inode_post_setxattr(dentry, name, value, size, flags);
+ security_ops->inode_post_setxattr(dentry, mnt, name, value, size, flags);
+ security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
+ flags);
}
int security_inode_getxattr(struct dentry *dentry, char *name)
int security_inode_getxattr(struct dentry *dentry, const char *name)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2332,7 +2332,9 @@ static int selinux_inode_setotherxattr(s
@@ -2655,8 +2655,9 @@ static int selinux_inode_setotherxattr(s
return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
}
-static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
-static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags)
+ const char *name, const void *value,
+ size_t size, int flags)
{
struct task_security_struct *tsec = current->security;
struct inode *inode = dentry->d_inode;
@@ -2381,7 +2383,9 @@ static int selinux_inode_setxattr(struct
@@ -2705,7 +2706,8 @@ static int selinux_inode_setxattr(struct
&ad);
}
-static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
-static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
+static void selinux_inode_post_setxattr(struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name,
void *value, size_t size, int flags)
+ struct vfsmount *mnt, const char *name,
const void *value, size_t size,
int flags)
{
struct inode *inode = dentry->d_inode;

View file

@ -17,7 +17,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2277,7 +2277,7 @@ int vfs_symlink(struct inode *dir, struc
@@ -2422,7 +2422,7 @@ int vfs_symlink(struct inode *dir, struc
if (!dir->i_op || !dir->i_op->symlink)
return -EPERM;
@ -28,7 +28,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -315,6 +315,7 @@ struct request_sock;
@@ -359,6 +359,7 @@ static inline void security_free_mnt_opt
* 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.
@ -36,7 +36,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* @old_name contains the pathname of file.
* Return 0 if permission is granted.
* @inode_mkdir:
@@ -1256,8 +1257,8 @@ struct security_operations {
@@ -1364,8 +1365,8 @@ struct security_operations {
int (*inode_link) (struct dentry *old_dentry,
struct inode *dir, struct dentry *new_dentry);
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
@ -47,7 +47,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
@@ -1515,7 +1516,7 @@ int security_inode_link(struct dentry *o
@@ -1640,7 +1641,7 @@ int security_inode_link(struct dentry *o
struct dentry *new_dentry);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
@ -56,7 +56,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
@@ -1844,6 +1845,7 @@ static inline int security_inode_unlink
@@ -1999,6 +2000,7 @@ static inline int security_inode_unlink(
static inline int security_inode_symlink(struct inode *dir,
struct dentry *dentry,
@ -66,7 +66,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -279,7 +279,7 @@ static int dummy_inode_unlink (struct in
@@ -306,7 +306,7 @@ static int dummy_inode_unlink (struct in
}
static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry,
@ -77,7 +77,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -352,11 +352,11 @@ int security_inode_unlink(struct inode *
@@ -412,11 +412,11 @@ int security_inode_unlink(struct inode *
}
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
@ -93,7 +93,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2210,7 +2210,8 @@ static int selinux_inode_unlink(struct i
@@ -2533,7 +2533,8 @@ static int selinux_inode_unlink(struct i
return may_link(dir, dentry, MAY_UNLINK);
}

View file

@ -17,7 +17,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2184,7 +2184,7 @@ int vfs_unlink(struct inode *dir, struct
@@ -2324,7 +2324,7 @@ int vfs_unlink(struct inode *dir, struct
if (d_mountpoint(dentry))
error = -EBUSY;
else {
@ -28,7 +28,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -312,6 +312,7 @@ struct request_sock;
@@ -356,6 +356,7 @@ static inline void security_free_mnt_opt
* 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.
@ -36,7 +36,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* Return 0 if permission is granted.
* @inode_symlink:
* Check the permission to create a symbolic link to a file.
@@ -1261,7 +1262,8 @@ struct security_operations {
@@ -1369,7 +1370,8 @@ struct security_operations {
int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt,
struct inode *dir, struct dentry *new_dentry,
struct vfsmount *new_mnt);
@ -46,7 +46,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, const char *old_name);
int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
@@ -1521,7 +1523,8 @@ int security_inode_create(struct inode *
@@ -1646,7 +1648,8 @@ int security_inode_create(struct inode *
int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
struct inode *dir, struct dentry *new_dentry,
struct vfsmount *new_mnt);
@ -56,7 +56,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, const char *old_name);
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
@@ -1848,7 +1851,8 @@ static inline int security_inode_link (s
@@ -2003,7 +2006,8 @@ static inline int security_inode_link(st
}
static inline int security_inode_unlink(struct inode *dir,
@ -68,7 +68,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -275,7 +275,8 @@ static int dummy_inode_link (struct dent
@@ -302,7 +302,8 @@ static int dummy_inode_link (struct dent
return 0;
}
@ -80,7 +80,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
--- a/security/security.c
+++ b/security/security.c
@@ -346,11 +346,12 @@ int security_inode_link(struct dentry *o
@@ -406,11 +406,12 @@ int security_inode_link(struct dentry *o
new_dentry, new_mnt);
}
@ -97,7 +97,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2205,11 +2205,12 @@ static int selinux_inode_link(struct den
@@ -2528,11 +2528,12 @@ static int selinux_inode_link(struct den
return may_link(dir, old_dentry, MAY_LINK);
}

View file

@ -9,27 +9,27 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 58 ++++++++++++++++++++++++-----------------------
include/linux/security.h | 40 +++++++++++++++++++-------------
fs/xattr.c | 61 +++++++++++++++++++++++++----------------------
include/linux/security.h | 38 ++++++++++++++++-------------
include/linux/xattr.h | 8 +++---
security/commoncap.c | 4 +--
security/dummy.c | 10 ++++----
security/security.c | 21 +++++++++--------
security/selinux/hooks.c | 10 ++++----
7 files changed, 84 insertions(+), 67 deletions(-)
security/dummy.c | 9 +++---
security/security.c | 17 ++++++-------
security/selinux/hooks.c | 10 ++++---
7 files changed, 81 insertions(+), 66 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -69,7 +69,7 @@ xattr_permission(struct inode *inode, co
@@ -68,7 +68,7 @@ xattr_permission(struct inode *inode, co
int
vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
- void *value, size_t size, int flags)
+ void *value, size_t size, int flags, struct file *file)
vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags, struct file *file)
{
struct inode *inode = dentry->d_inode;
int error;
@@ -79,7 +79,7 @@ vfs_setxattr(struct dentry *dentry, stru
@@ -78,7 +78,7 @@ vfs_setxattr(struct dentry *dentry, stru
return error;
mutex_lock(&inode->i_mutex);
@ -38,16 +38,16 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (error)
goto out;
error = -EOPNOTSUPP;
@@ -106,7 +106,7 @@ EXPORT_SYMBOL_GPL(vfs_setxattr);
@@ -132,7 +132,7 @@ EXPORT_SYMBOL_GPL(xattr_getsecurity);
ssize_t
vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
- void *value, size_t size)
+ void *value, size_t size, struct file *file)
{
struct inode *inode = dentry->d_inode;
int error;
@@ -115,7 +115,7 @@ vfs_getxattr(struct dentry *dentry, stru
@@ -141,7 +141,7 @@ vfs_getxattr(struct dentry *dentry, stru
if (error)
return error;
@ -56,7 +56,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (error)
return error;
@@ -143,12 +143,12 @@ EXPORT_SYMBOL_GPL(vfs_getxattr);
@@ -169,12 +169,12 @@ EXPORT_SYMBOL_GPL(vfs_getxattr);
ssize_t
vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
@ -71,17 +71,17 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (error)
return error;
error = -EOPNOTSUPP;
@@ -164,7 +164,8 @@ vfs_listxattr(struct dentry *dentry, str
@@ -190,7 +190,8 @@ vfs_listxattr(struct dentry *dentry, str
EXPORT_SYMBOL_GPL(vfs_listxattr);
int
-vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name)
+vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
-vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name)
+vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
+ struct file *file)
{
struct inode *inode = dentry->d_inode;
int error;
@@ -176,7 +177,7 @@ vfs_removexattr(struct dentry *dentry, s
@@ -202,7 +203,7 @@ vfs_removexattr(struct dentry *dentry, s
if (error)
return error;
@ -90,16 +90,16 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (error)
return error;
@@ -196,7 +197,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
@@ -222,7 +223,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
*/
static long
setxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
- void __user *value, size_t size, int flags)
+ void __user *value, size_t size, int flags, struct file *file)
setxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
- const void __user *value, size_t size, int flags)
+ const void __user *value, size_t size, int flags, struct file *file)
{
int error;
void *kvalue = NULL;
@@ -223,7 +224,7 @@ setxattr(struct dentry *dentry, struct v
@@ -249,7 +250,7 @@ setxattr(struct dentry *dentry, struct v
}
}
@ -108,43 +108,46 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
kfree(kvalue);
return error;
}
@@ -238,7 +239,7 @@ sys_setxattr(char __user *path, char __u
error = user_path_walk(path, &nd);
if (error)
return error;
- error = setxattr(nd.dentry, nd.mnt, name, value, size, flags);
+ error = setxattr(nd.dentry, nd.mnt, name, value, size, flags, NULL);
path_release(&nd);
@@ -266,7 +267,8 @@ sys_setxattr(const char __user *path, co
return error;
error = mnt_want_write(nd.path.mnt);
if (!error) {
- error = setxattr(nd.path.dentry, nd.path.mnt, name, value, size, flags);
+ error = setxattr(nd.path.dentry, nd.path.mnt, name, value, size,
+ flags, NULL);
mnt_drop_write(nd.path.mnt);
}
@@ -253,7 +254,7 @@ sys_lsetxattr(char __user *path, char __
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = setxattr(nd.dentry, nd.mnt, name, value, size, flags);
+ error = setxattr(nd.dentry, nd.mnt, name, value, size, flags, NULL);
path_release(&nd);
path_put(&nd.path);
@@ -285,7 +287,8 @@ sys_lsetxattr(const char __user *path, c
return error;
error = mnt_want_write(nd.path.mnt);
if (!error) {
- error = setxattr(nd.path.dentry, nd.path.mnt, name, value, size, flags);
+ error = setxattr(nd.path.dentry, nd.path.mnt, name, value, size,
+ flags, NULL);
mnt_drop_write(nd.path.mnt);
}
@@ -271,7 +272,7 @@ sys_fsetxattr(int fd, char __user *name,
return error;
dentry = f->f_path.dentry;
path_put(&nd.path);
@@ -307,7 +310,8 @@ sys_fsetxattr(int fd, const char __user
audit_inode(NULL, dentry);
error = mnt_want_write(f->f_path.mnt);
if (!error) {
- error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags);
+ error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags, f);
fput(f);
return error;
+ error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags,
+ f);
mnt_drop_write(f->f_path.mnt);
}
@@ -281,7 +282,7 @@ sys_fsetxattr(int fd, char __user *name,
fput(f);
@@ -319,7 +323,7 @@ sys_fsetxattr(int fd, const char __user
*/
static ssize_t
getxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
getxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
- void __user *value, size_t size)
+ void __user *value, size_t size, struct file *file)
{
ssize_t error;
void *kvalue = NULL;
@@ -301,7 +302,7 @@ getxattr(struct dentry *dentry, struct v
@@ -339,7 +343,7 @@ getxattr(struct dentry *dentry, struct v
return -ENOMEM;
}
@ -153,25 +156,25 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (error > 0) {
if (size && copy_to_user(value, kvalue, error))
error = -EFAULT;
@@ -324,7 +325,7 @@ sys_getxattr(char __user *path, char __u
@@ -362,7 +366,7 @@ sys_getxattr(const char __user *path, co
error = user_path_walk(path, &nd);
if (error)
return error;
- error = getxattr(nd.dentry, nd.mnt, name, value, size);
+ error = getxattr(nd.dentry, nd.mnt, name, value, size, NULL);
path_release(&nd);
- error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size);
+ error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
path_put(&nd.path);
return error;
}
@@ -339,7 +340,7 @@ sys_lgetxattr(char __user *path, char __
@@ -377,7 +381,7 @@ sys_lgetxattr(const char __user *path, c
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = getxattr(nd.dentry, nd.mnt, name, value, size);
+ error = getxattr(nd.dentry, nd.mnt, name, value, size, NULL);
path_release(&nd);
- error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size);
+ error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
path_put(&nd.path);
return error;
}
@@ -354,7 +355,7 @@ sys_fgetxattr(int fd, char __user *name,
@@ -392,7 +396,7 @@ sys_fgetxattr(int fd, const char __user
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
@ -180,7 +183,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
fput(f);
return error;
}
@@ -364,7 +365,7 @@ sys_fgetxattr(int fd, char __user *name,
@@ -402,7 +406,7 @@ sys_fgetxattr(int fd, const char __user
*/
static ssize_t
listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
@ -189,7 +192,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
{
ssize_t error;
char *klist = NULL;
@@ -377,7 +378,7 @@ listxattr(struct dentry *dentry, struct
@@ -415,7 +419,7 @@ listxattr(struct dentry *dentry, struct
return -ENOMEM;
}
@ -198,25 +201,25 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
if (error > 0) {
if (size && copy_to_user(list, klist, error))
error = -EFAULT;
@@ -399,7 +400,7 @@ sys_listxattr(char __user *path, char __
@@ -437,7 +441,7 @@ sys_listxattr(const char __user *path, c
error = user_path_walk(path, &nd);
if (error)
return error;
- error = listxattr(nd.dentry, nd.mnt, list, size);
+ error = listxattr(nd.dentry, nd.mnt, list, size, NULL);
path_release(&nd);
- error = listxattr(nd.path.dentry, nd.path.mnt, list, size);
+ error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
path_put(&nd.path);
return error;
}
@@ -413,7 +414,7 @@ sys_llistxattr(char __user *path, char _
@@ -451,7 +455,7 @@ sys_llistxattr(const char __user *path,
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = listxattr(nd.dentry, nd.mnt, list, size);
+ error = listxattr(nd.dentry, nd.mnt, list, size, NULL);
path_release(&nd);
- error = listxattr(nd.path.dentry, nd.path.mnt, list, size);
+ error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
path_put(&nd.path);
return error;
}
@@ -428,7 +429,7 @@ sys_flistxattr(int fd, char __user *list
@@ -466,7 +470,7 @@ sys_flistxattr(int fd, char __user *list
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
@ -225,17 +228,17 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
fput(f);
return error;
}
@@ -437,7 +438,8 @@ sys_flistxattr(int fd, char __user *list
@@ -475,7 +479,8 @@ sys_flistxattr(int fd, char __user *list
* Extended attribute REMOVE operations
*/
static long
-removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name)
+removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
+ struct file *file)
-removexattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name)
+removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ const char __user *name, struct file *file)
{
int error;
char kname[XATTR_NAME_MAX + 1];
@@ -448,7 +450,7 @@ removexattr(struct dentry *dentry, struc
@@ -486,7 +491,7 @@ removexattr(struct dentry *dentry, struc
if (error < 0)
return error;
@ -244,97 +247,96 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
asmlinkage long
@@ -460,7 +462,7 @@ sys_removexattr(char __user *path, char
error = user_path_walk(path, &nd);
if (error)
return error;
- error = removexattr(nd.dentry, nd.mnt, name);
+ error = removexattr(nd.dentry, nd.mnt, name, NULL);
path_release(&nd);
@@ -500,7 +505,7 @@ sys_removexattr(const char __user *path,
return error;
error = mnt_want_write(nd.path.mnt);
if (!error) {
- error = removexattr(nd.path.dentry, nd.path.mnt, name);
+ error = removexattr(nd.path.dentry, nd.path.mnt, name, NULL);
mnt_drop_write(nd.path.mnt);
}
@@ -474,7 +476,7 @@ sys_lremovexattr(char __user *path, char
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = removexattr(nd.dentry, nd.mnt, name);
+ error = removexattr(nd.dentry, nd.mnt, name, NULL);
path_release(&nd);
path_put(&nd.path);
@@ -518,7 +523,7 @@ sys_lremovexattr(const char __user *path
return error;
error = mnt_want_write(nd.path.mnt);
if (!error) {
- error = removexattr(nd.path.dentry, nd.path.mnt, name);
+ error = removexattr(nd.path.dentry, nd.path.mnt, name, NULL);
mnt_drop_write(nd.path.mnt);
}
@@ -491,7 +493,7 @@ sys_fremovexattr(int fd, char __user *na
return error;
dentry = f->f_path.dentry;
path_put(&nd.path);
@@ -539,7 +544,7 @@ sys_fremovexattr(int fd, const char __us
audit_inode(NULL, dentry);
error = mnt_want_write(f->f_path.mnt);
if (!error) {
- error = removexattr(dentry, f->f_path.mnt, name);
+ error = removexattr(dentry, f->f_path.mnt, name, f);
fput(f);
return error;
mnt_drop_write(f->f_path.mnt);
}
fput(f);
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -56,8 +56,8 @@ extern void cap_capset_set (struct task_
extern int cap_bprm_set_security (struct linux_binprm *bprm);
extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
@@ -55,9 +55,9 @@ extern void cap_bprm_apply_creds(struct
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
-extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name);
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags, struct file *file);
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name, struct file *file);
extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
const char *name, const void *value, size_t size,
- int flags);
+ int flags, struct file *file);
extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- const char *name);
+ const char *name, struct file *file);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
@@ -1286,16 +1286,18 @@ struct security_operations {
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
@@ -1397,16 +1397,17 @@ struct security_operations {
void (*inode_delete) (struct inode *inode);
int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
- char *name, void *value, size_t size, int flags);
+ char *name, void *value, size_t size, int flags,
+ struct file *file);
const char *name, const void *value, size_t size,
- int flags);
+ int flags, struct file *file);
void (*inode_post_setxattr) (struct dentry *dentry,
struct vfsmount *mnt,
char *name, void *value,
const char *name, const void *value,
size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
- char *name);
- const char *name);
- int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
+ char *name, struct file *file);
+ const char *name, struct file *file);
+ int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file);
int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
- char *name);
+ char *name, struct file *file);
- const char *name);
+ const char *name, struct file *file);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
@@ -1552,15 +1554,17 @@ int security_inode_setattr(struct dentry
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -1681,15 +1682,16 @@ int security_inode_getattr(struct vfsmou
void security_inode_delete(struct inode *inode);
int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name, void *value, size_t size, int flags);
+ char *name, void *value, size_t size, int flags,
+ struct file *file);
const char *name, const void *value,
- size_t size, int flags);
+ size_t size, int flags, struct file *file);
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
int flags);
const char *name, const void *value,
size_t size, int flags);
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name);
- const char *name);
-int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
+ char *name, struct file *file);
+ const char *name, struct file *file);
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file);
int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name);
+ char *name, struct file *file);
- const char *name);
+ const char *name, struct file *file);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
@@ -1946,9 +1950,10 @@ static inline void security_inode_delete
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -2106,9 +2108,10 @@ static inline void security_inode_delete
static inline int security_inode_setxattr(struct dentry *dentry,
struct vfsmount *mnt, char *name,
- void *value, size_t size, int flags)
+ void *value, size_t size, int flags,
struct vfsmount *mnt,
const char *name, const void *value,
- size_t size, int flags)
+ size_t size, int flags,
+ struct file *file)
{
- return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
@ -342,12 +344,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
static inline void security_inode_post_setxattr(struct dentry *dentry,
@@ -1959,21 +1964,24 @@ static inline void security_inode_post_s
{ }
@@ -2120,22 +2123,25 @@ static inline void security_inode_post_s
static inline int security_inode_getxattr(struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
struct vfsmount *mnt,
- const char *name)
+ const char *name,
+ struct file *file)
{
return 0;
@ -362,8 +364,9 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
static inline int security_inode_removexattr(struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
struct vfsmount *mnt,
- const char *name)
+ const char *name,
+ struct file *file)
{
- return cap_inode_removexattr(dentry, mnt, name);
@ -373,61 +376,58 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
static inline int security_inode_need_killpriv(struct dentry *dentry)
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -47,12 +47,12 @@ struct xattr_handler {
@@ -47,10 +47,10 @@ struct xattr_handler {
};
ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
- size_t);
+ size_t, struct file *);
ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list,
- size_t size);
+ size_t size, struct file *);
int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
- int);
-int vfs_removexattr(struct dentry *, struct vfsmount *, char *);
+ int, struct file *);
+int vfs_removexattr(struct dentry *, struct vfsmount *, char *, struct file *);
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
-ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t);
-ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size);
-int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int);
-int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *);
+ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t, struct file *file);
+ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size, struct file *file);
+int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int, struct file *file);
+int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *, struct file *file);
ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -369,7 +369,7 @@ int cap_bprm_secureexec (struct linux_bi
}
@@ -385,7 +385,7 @@ int cap_bprm_secureexec (struct linux_bi
int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
- void *value, size_t size, int flags)
+ void *value, size_t size, int flags, struct file *file)
int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
const char *name, const void *value, size_t size,
- int flags)
+ int flags, struct file *file)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
@@ -383,7 +383,7 @@ int cap_inode_setxattr(struct dentry *de
@@ -399,7 +399,7 @@ int cap_inode_setxattr(struct dentry *de
}
int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
- const char *name)
+ const char *name, struct file *file)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -349,7 +349,7 @@ static void dummy_inode_delete (struct i
@@ -376,7 +376,7 @@ static void dummy_inode_delete (struct i
static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
- int flags)
+ int flags, struct file *file)
const char *name, const void *value,
- size_t size, int flags)
+ size_t size, int flags, struct file *file)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -366,18 +366,20 @@ static void dummy_inode_post_setxattr (s
@@ -393,18 +393,19 @@ static void dummy_inode_post_setxattr (s
}
static int dummy_inode_getxattr (struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
+ struct file *file)
static int dummy_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt,
- const char *name)
+ const char *name, struct file *file)
{
return 0;
}
@ -440,20 +440,19 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
- const char *name)
+ const char *name, struct file *file)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
--- a/security/security.c
+++ b/security/security.c
@@ -441,12 +441,13 @@ void security_inode_delete(struct inode
}
@@ -502,12 +502,12 @@ void security_inode_delete(struct inode
int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name, void *value, size_t size, int flags)
+ char *name, void *value, size_t size, int flags,
+ struct file *file)
const char *name, const void *value, size_t size,
- int flags)
+ int flags, struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
@ -463,18 +462,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
@@ -455,30 +456,32 @@ void security_inode_post_setxattr(struct
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return;
- security_ops->inode_post_setxattr(dentry, mnt, name, value, size, flags);
+ security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
+ flags);
@@ -521,26 +521,27 @@ void security_inode_post_setxattr(struct
}
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
- const char *name)
+ const char *name, struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
@ -493,8 +486,8 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
- const char *name)
+ const char *name, struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
@ -505,21 +498,21 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
int security_inode_need_killpriv(struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2334,7 +2334,7 @@ static int selinux_inode_setotherxattr(s
@@ -2657,7 +2657,7 @@ static int selinux_inode_setotherxattr(s
static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
- int flags)
+ int flags, struct file *file)
const char *name, const void *value,
- size_t size, int flags)
+ size_t size, int flags, struct file *file)
{
struct task_security_struct *tsec = current->security;
struct inode *inode = dentry->d_inode;
@@ -2410,18 +2410,20 @@ static void selinux_inode_post_setxattr(
@@ -2733,18 +2733,20 @@ static void selinux_inode_post_setxattr(
}
static int selinux_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
- const char *name)
+ const char *name, struct file *file)
{
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
@ -532,8 +525,8 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
}
static int selinux_inode_removexattr(struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
- struct vfsmount *mnt, const char *name)
+ struct vfsmount *mnt, const char *name,
+ struct file *file)
{
if (strcmp(name, XATTR_NAME_SELINUX))

View file

@ -1,85 +0,0 @@
Index: linux-2.6/fs/open.c
===================================================================
--- linux-2.6.orig/fs/open.c
+++ linux-2.6/fs/open.c
@@ -483,6 +483,10 @@ asmlinkage long sys_chroot(const char __
if (!capable(CAP_SYS_CHROOT))
goto dput_and_out;
+ error = security_chroot(&nd);
+ if (error)
+ goto dput_and_out;
+
set_fs_root(current->fs, nd.mnt, nd.dentry);
set_fs_altroot();
error = 0;
Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/include/linux/security.h
@@ -247,6 +247,9 @@ struct request_sock;
* Update module state after a successful pivot.
* @old_nd contains the nameidata structure for the old root.
* @new_nd contains the nameidata structure for the new root.
+ * @sb_chroot:
+ * Check permission before chroot to chroot to point named by @nd
+ * @nd contains the nameidata object for the new root
*
* Security hooks for inode operations.
*
@@ -1211,6 +1214,7 @@ struct security_operations {
struct nameidata * new_nd);
void (*sb_post_pivotroot) (struct nameidata * old_nd,
struct nameidata * new_nd);
+ int (*sb_chroot) (struct nameidata * nd);
int (*inode_alloc_security) (struct inode *inode);
void (*inode_free_security) (struct inode *inode);
@@ -1610,6 +1614,11 @@ static inline void security_sb_post_pivo
security_ops->sb_post_pivotroot (old_nd, new_nd);
}
+static inline int security_chroot (struct nameidata *nd)
+{
+ return security_ops->sb_chroot (nd);
+}
+
static inline int security_inode_alloc (struct inode *inode)
{
inode->i_security = NULL;
@@ -2362,6 +2371,11 @@ static inline void security_sb_post_pivo
struct nameidata *new_nd)
{ }
+static inline int security_sb_chroot (struct nameidata *nd)
+{
+ return 0;
+}
+
static inline int security_inode_alloc (struct inode *inode)
{
return 0;
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/security/dummy.c
@@ -248,6 +248,11 @@ static void dummy_sb_post_pivotroot (str
return;
}
+static int dummy_sb_chroot (struct nameidata *nd)
+{
+ return 0;
+}
+
static int dummy_inode_alloc_security (struct inode *inode)
{
return 0;
@@ -1004,6 +1009,7 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, sb_post_addmount);
set_to_dummy_if_null(ops, sb_pivotroot);
set_to_dummy_if_null(ops, sb_post_pivotroot);
+ set_to_dummy_if_null(ops, sb_chroot);
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);

View file

@ -1,9 +1,6 @@
#unionfs-2.2.2_for_2.6.24-rc7.diff
#unionfs-2.1.11_for_2.6.24-rc4.diff
security-create.diff
remove_suid.diff
vfs-notify_change.diff
#should_remove_suid.diff
security-setattr.diff
vfs-mkdir.diff
security-mkdir.diff
@ -30,12 +27,10 @@ security-listxattr.diff
vfs-removexattr.diff
security-removexattr.diff
unambiguous-__d_path.diff
mount-consistent-__d_path.diff
d_namespace_path.diff
__d_path-keep-connected.diff
fsetattr.diff
#fix-fuse.diff
fsetattr-reintro-ATTR_FILE.diff
fsetattr-restore-ia_file.diff
file-handle-ops.diff
security-xattr-file.diff
sysctl-pathname.diff
@ -49,75 +44,7 @@ apparmor-lsm.diff
apparmor-module_interface.diff
apparmor-misc.diff
apparmor-intree.diff
#fix-rcu-deref.diff
#fix-name-errorpath.diff
#change-profile-kernel-v2.diff
#expand-dfa.diff
#slash-null-dfa.diff
#profile-namespaces.diff
#owner-perm-set.diff
#apparmor-link-pairs.diff
#apparmor-bootdisable.diff
#apparmor-builtin-only.diff
#apparmor-security-goal.diff
#apparmor-features.diff
#split_init.diff
#apparmor-fix-sysctl-refcount.diff
#apparmor-fix-lock-letter.diff
#fix-link-subset.diff
#hat_perm.diff
#extend-x-mods.diff
#no-safex-link-subset.diff
#apparmor-create-append.diff
#apparmor-failed-name-error.diff
#audit-uid.diff
#apparmor-secondary-accept.diff
#apparmor-audit-flags2.diff
#fix-profile-namespaces.diff
#fix-dfa.diff
#cap-set.diff
#foobar.diff
# # NOT YET
# ecryptfs-d_revalidate.diff
# nfs-nameidata-check.diff
# # statvfs.diff
# # statvfs-2.diff
# # fix-getcwd.diff
# # proc-mounts-cleanup.diff
# # proc-mounts-check-d_path-result.diff
# # fix-d_path.diff
##split-up-nameidata.diff
##vfs_create-nameidata.diff
##xattr_permission.diff
##nfsd_permission-nameidata.diff
# vfs_create-args.diff
# vfs_mknod-args.diff
# vfs_mkdir-args.diff
# vfs_symlink-args.diff
# vfs_link-args.diff
# vfs_rename-args.diff
# may_create-args.diff
# vfs_rmdir-args.diff
# vfs_unlink-args.diff
# may_delete-args.diff
#fix-change_profile-namespace.diff
#audit_denied.diff
#apparmor-audit-flags.diff
#FS2.2.2_fix-unionfs-with-AppArmor.patch
#FS2.1.3_fix-unionfs-with-AppArmor.patch
#named-transitions.diff
apparmor-network.diff
#fix-net.diff
apparmor-rlimits.diff
audit-log-type-in-syslog.diff
#fix-named-transitions.diff
#apparmor-xmods-accept-entry.diff
#apparmor-split-audit-deny.diff
#apparmor-cond-uid.diff
#apparmor-quiet-control.diff
#apparmor-direct-complain.diff
apparmor-2.6.25.diff
apparmor-stack_secondary.diff

View file

@ -1,96 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Pass struct file down to should_remove_suid and children
Pass struct path to should_remove_suid instead of only the dentry.
To make should_remove_suid consistent with changes made to
remove_suid.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/ocfs2/file.c | 2 +-
fs/open.c | 5 ++++-
fs/splice.c | 2 +-
include/linux/fs.h | 2 +-
mm/filemap.c | 6 +++---
5 files changed, 10 insertions(+), 7 deletions(-)
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1191,7 +1191,7 @@ static int ocfs2_prepare_inode_for_write
* inode. There's also the dinode i_size state which
* can be lost via setattr during extending writes (we
* set inode->i_size at the end of a write. */
- if (should_remove_suid(path->dentry)) {
+ if (should_remove_suid(path)) {
if (meta_level == 0) {
ocfs2_meta_unlock(inode, meta_level);
meta_level = 1;
--- a/fs/open.c
+++ b/fs/open.c
@@ -198,6 +198,7 @@ int do_truncate(struct dentry *dentry, s
{
int err;
struct iattr newattrs;
+ struct path path;
/* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
if (length < 0)
@@ -211,7 +212,9 @@ int do_truncate(struct dentry *dentry, s
}
/* Remove suid/sgid on truncate too */
- newattrs.ia_valid |= should_remove_suid(dentry);
+ path.dentry = dentry;
+ path.mnt = mnt;
+ newattrs.ia_valid |= should_remove_suid(&path);
mutex_lock(&dentry->d_inode->i_mutex);
err = notify_change(dentry, mnt, &newattrs);
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -842,7 +842,7 @@ generic_file_splice_write(struct pipe_in
ssize_t ret;
int err;
- err = should_remove_suid(out->f_path.dentry);
+ err = should_remove_suid(&out->f_path);
if (unlikely(err)) {
mutex_lock(&inode->i_mutex);
err = __remove_suid(&out->f_path, err);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1698,7 +1698,7 @@ extern void clear_inode(struct inode *);
extern void destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *);
extern int __remove_suid(struct path *, int);
-extern int should_remove_suid(struct dentry *);
+extern int should_remove_suid(struct path *);
extern int remove_suid(struct path *);
extern void __insert_inode_hash(struct inode *, unsigned long hashval);
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1882,9 +1882,9 @@ repeat:
* if suid or (sgid and xgrp)
* remove privs
*/
-int should_remove_suid(struct dentry *dentry)
+int should_remove_suid(struct path *path)
{
- mode_t mode = dentry->d_inode->i_mode;
+ mode_t mode = path->dentry->d_inode->i_mode;
int kill = 0;
/* suid always must be killed */
@@ -1915,7 +1915,7 @@ int __remove_suid(struct path *path, int
int remove_suid(struct path *path)
{
- int kill = should_remove_suid(path->dentry);
+ int kill = should_remove_suid(path);
if (unlikely(kill))
return __remove_suid(path, kill);

View file

@ -1,40 +0,0 @@
convert the null transition from using the 0 character to "//" until
the parser gets updated so that it can add a null character transition.
---
security/apparmor/match.c | 24 +-----------------------
1 file changed, 1 insertion(+), 23 deletions(-)
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -262,29 +262,7 @@ unsigned int aa_dfa_next_state(struct aa
*/
unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
{
- u16 *def = DEFAULT_TABLE(dfa);
- u32 *base = BASE_TABLE(dfa);
- u16 *next = NEXT_TABLE(dfa);
- u16 *check = CHECK_TABLE(dfa);
- unsigned int state = start, pos;
-
- /* current state is <state>, matching character *str */
- if (dfa->tables[YYTD_ID_EC - 1]) {
- u8 *equiv = EQUIV_TABLE(dfa);
- pos = base[state] + equiv[0];
- if (check[pos] == state)
- state = next[pos];
- else
- state = def[state];
- } else {
- pos = base[state] + 0;
- if (check[pos] == state)
- state = next[pos];
- else
- state = def[state];
- }
-
- return state;
+ return aa_dfa_next_state(dfa, start, "//");
}
/**

File diff suppressed because it is too large Load diff

View file

@ -1,215 +0,0 @@
---
security/apparmor/Kconfig | 15 ++++++
security/apparmor/apparmor.h | 5 ++
security/apparmor/apparmorfs.c | 8 +++
security/apparmor/lsm.c | 95 ++++++++++++++++++++++++++++++++++-------
4 files changed, 109 insertions(+), 14 deletions(-)
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -25,3 +25,18 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
bootup.
If you are unsure how to answer this question, answer 1.
+
+config SECURITY_APPARMOR_DISABLE
+ bool "AppArmor runtime disable"
+ depends on SECURITY_APPARMOR
+ default n
+ help
+ This option enables writing to a apparmorfs node 'disable', which
+ allows AppArmor to be disabled at runtime prior to the policy load.
+ AppArmor will then remain disabled until the next boot.
+ This option is similar to the apparmor.enabled=0 boot parameter,
+ but is to support runtime disabling of AppArmor, e.g. from
+ /sbin/init, for portability across platforms where boot
+ parameters are difficult to employ.
+
+ If you are unsure how to answer this question, answer N.
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -284,6 +284,11 @@ extern int aa_net_perm(struct aa_profile
int family, int type, int protocol);
extern int aa_revalidate_sk(struct sock *sk, char *operation);
+/* lsm.c */
+extern int apparmor_initialized;
+extern void info_message(const char *str);
+extern void apparmor_disable(void);
+
/* list.c */
extern struct aa_namespace *__aa_find_namespace(const char *name,
struct list_head *list);
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -231,6 +231,9 @@ int create_apparmorfs(void)
{
int error;
+ if (!apparmor_initialized)
+ return 0;
+
if (apparmor_dentry) {
AA_ERROR("%s: AppArmor securityfs already exists\n",
__FUNCTION__);
@@ -262,11 +265,16 @@ int create_apparmorfs(void)
if (error)
goto error;
+ /* Report that AppArmor fs is enabled */
+ info_message("AppArmor Filesystem Enabled");
return 0;
error:
destroy_apparmorfs();
AA_ERROR("Error creating AppArmor securityfs\n");
+ apparmor_disable();
return error;
}
+fs_initcall(create_apparmorfs);
+
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -23,16 +23,8 @@
#include "apparmor.h"
#include "inline.h"
-/* Boot time disable flag */
-int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
-
-static int __init apparmor_enabled_setup(char *str)
-{
- apparmor_enabled = simple_strtol(str, NULL, 0);
- return 1;
-}
-__setup("apparmor=", apparmor_enabled_setup);
-
+/* Flag indicating whether initialization completed */
+int apparmor_initialized = 0;
static int param_set_aabool(const char *val, struct kernel_param *kp);
static int param_get_aabool(char *buffer, struct kernel_param *kp);
@@ -75,6 +67,25 @@ unsigned int apparmor_path_max = 2 * PAT
module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
+/* Boot time disable flag */
+#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
+#define AA_ENABLED_PERMS 0600
+#else
+#define AA_ENABLED_PERMS 0400
+#endif
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
+unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
+module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
+ &apparmor_enabled, AA_ENABLED_PERMS);
+MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
+
+static int __init apparmor_enabled_setup(char *str)
+{
+ apparmor_enabled = simple_strtol(str, NULL, 0);
+ return 1;
+}
+__setup("apparmor=", apparmor_enabled_setup);
+
static int param_set_aabool(const char *val, struct kernel_param *kp)
{
if (aa_task_context(current))
@@ -103,6 +114,35 @@ static int param_get_aauint(char *buffer
return param_get_uint(buffer, kp);
}
+/* allow run time disabling of apparmor */
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ unsigned long l;
+
+ if (!apparmor_initialized) {
+ apparmor_enabled = 0;
+ return 0;
+ }
+
+ if (aa_task_context(current))
+ return -EPERM;
+
+ if (!apparmor_enabled)
+ return -EINVAL;
+
+ if (!val)
+ return -EINVAL;
+
+ l = simple_strtoul(val, &endp, 0);
+ if (endp == val || l != 0)
+ return -EINVAL;
+
+ apparmor_enabled = 0;
+ apparmor_disable();
+ return 0;
+}
+
static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
const char *name)
{
@@ -879,14 +919,15 @@ struct security_operations apparmor_ops
.socket_shutdown = apparmor_socket_shutdown,
};
-static void info_message(const char *str)
+void info_message(const char *str)
{
struct aa_audit sa;
memset(&sa, 0, sizeof(sa));
sa.gfp_mask = GFP_KERNEL;
sa.info = str;
- printk(KERN_INFO "AppArmor: %s", str);
- aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
+ printk(KERN_INFO "AppArmor: %s\n", str);
+ if (audit_enabled)
+ aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
}
static int __init apparmor_init(void)
@@ -913,6 +954,8 @@ static int __init apparmor_init(void)
goto register_security_out;
}
+ /* Report that AppArmor successfully initialized */
+ apparmor_initialized = 1;
if (apparmor_complain)
info_message("AppArmor initialized: complainmode enabled");
else
@@ -931,7 +974,31 @@ createfs_out:
}
-module_init(apparmor_init);
+security_initcall(apparmor_init);
+
+void apparmor_disable(void)
+{
+ /* Remove and release all the profiles on the profile list. */
+ mutex_lock(&aa_interface_lock);
+ aa_profile_ns_list_release();
+
+ /* FIXME: cleanup profiles references on files */
+ free_default_namespace();
+
+ /*
+ * Delay for an rcu cycle to make sure that all active task
+ * context readers have finished, and all profiles have been
+ * freed by their rcu callbacks.
+ */
+ synchronize_rcu();
+
+ destroy_apparmorfs();
+ mutex_unlock(&aa_interface_lock);
+
+ apparmor_initialized = 0;
+
+ info_message("AppArmor protection removed");
+}
MODULE_DESCRIPTION("AppArmor process confinement");
MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");

View file

@ -1,494 +0,0 @@
---
arch/alpha/kernel/osf_sys.c | 11 ++++----
arch/mips/kernel/sysirix.c | 12 ++++-----
arch/parisc/hpux/sys_hpux.c | 11 ++++----
arch/sparc64/solaris/fs.c | 16 ++++--------
fs/compat.c | 13 +++++-----
fs/ecryptfs/super.c | 5 +++-
fs/nfsd/nfs4xdr.c | 2 -
fs/nfsd/vfs.c | 2 -
fs/open.c | 53 ++++++++++++++++++++++++++++++++++---------
include/asm-arm/statfs.h | 6 +++-
include/asm-generic/statfs.h | 9 ++++---
include/asm-ia64/compat.h | 3 +-
include/asm-ia64/statfs.h | 9 ++++---
include/asm-parisc/compat.h | 3 +-
include/asm-parisc/statfs.h | 9 ++++---
include/asm-powerpc/compat.h | 3 +-
include/asm-powerpc/statfs.h | 9 ++++---
include/asm-s390/compat.h | 3 +-
include/asm-s390/statfs.h | 9 ++++---
include/asm-sparc64/compat.h | 3 +-
include/asm-sparc64/statfs.h | 9 ++++---
include/asm-x86_64/compat.h | 3 +-
include/asm-x86_64/statfs.h | 9 ++++---
include/linux/fs.h | 2 -
include/linux/statfs.h | 13 +++++++++-
kernel/acct.c | 2 -
26 files changed, 151 insertions(+), 78 deletions(-)
Index: linux-2.6-apparmor/arch/alpha/kernel/osf_sys.c
===================================================================
--- linux-2.6-apparmor.orig/arch/alpha/kernel/osf_sys.c
+++ linux-2.6-apparmor/arch/alpha/kernel/osf_sys.c
@@ -244,11 +244,11 @@ linux_to_osf_statfs(struct kstatfs *linu
}
static int
-do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,
- unsigned long bufsiz)
+do_osf_statfs(struct dentry * dentry, struct vfsmount *mnt,
+ struct osf_statfs __user *buffer, unsigned long bufsiz)
{
struct kstatfs linux_stat;
- int error = vfs_statfs(dentry, &linux_stat);
+ int error = vfs_statfs(dentry, mnt, &linux_stat);
if (!error)
error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
return error;
@@ -262,7 +262,7 @@ osf_statfs(char __user *path, struct osf
retval = user_path_walk(path, &nd);
if (!retval) {
- retval = do_osf_statfs(nd.dentry, buffer, bufsiz);
+ retval = do_osf_statfs(nd.dentry, nd.mnt, buffer, bufsiz);
path_release(&nd);
}
return retval;
@@ -277,7 +277,8 @@ osf_fstatfs(unsigned long fd, struct osf
retval = -EBADF;
file = fget(fd);
if (file) {
- retval = do_osf_statfs(file->f_path.dentry, buffer, bufsiz);
+ retval = do_osf_statfs(file->f_path.dentry, file->f_path.mnt,
+ buffer, bufsiz);
fput(file);
}
return retval;
Index: linux-2.6-apparmor/arch/mips/kernel/sysirix.c
===================================================================
--- linux-2.6-apparmor.orig/arch/mips/kernel/sysirix.c
+++ linux-2.6-apparmor/arch/mips/kernel/sysirix.c
@@ -694,7 +694,7 @@ asmlinkage int irix_statfs(const char __
if (error)
goto out;
- error = vfs_statfs(nd.dentry, &kbuf);
+ error = vfs_statfs(nd.dentry, nd.mnt, &kbuf);
if (error)
goto dput_and_out;
@@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int
goto out;
}
- error = vfs_statfs(file->f_path.dentry, &kbuf);
+ error = vfs_statfs(file->f_path.dentry, file->f_path.mnt, &kbuf);
if (error)
goto out_f;
@@ -1360,7 +1360,7 @@ asmlinkage int irix_statvfs(char __user
error = user_path_walk(fname, &nd);
if (error)
goto out;
- error = vfs_statfs(nd.dentry, &kbuf);
+ error = vfs_statfs(nd.dentry, nd.mnt, &kbuf);
if (error)
goto dput_and_out;
@@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, str
error = -EBADF;
goto out;
}
- error = vfs_statfs(file->f_path.dentry, &kbuf);
+ error = vfs_statfs(file->f_path.dentry, file->f_path.mnt, &kbuf);
if (error)
goto out_f;
@@ -1611,7 +1611,7 @@ asmlinkage int irix_statvfs64(char __use
error = user_path_walk(fname, &nd);
if (error)
goto out;
- error = vfs_statfs(nd.dentry, &kbuf);
+ error = vfs_statfs(nd.dentry, nd.mnt, &kbuf);
if (error)
goto dput_and_out;
@@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, s
error = -EBADF;
goto out;
}
- error = vfs_statfs(file->f_path.dentry, &kbuf);
+ error = vfs_statfs(file->f_path.dentry, file->f_path.mnt, &kbuf);
if (error)
goto out_f;
Index: linux-2.6-apparmor/arch/parisc/hpux/sys_hpux.c
===================================================================
--- linux-2.6-apparmor.orig/arch/parisc/hpux/sys_hpux.c
+++ linux-2.6-apparmor/arch/parisc/hpux/sys_hpux.c
@@ -145,7 +145,7 @@ static int hpux_ustat(dev_t dev, struct
s = user_get_super(dev);
if (s == NULL)
goto out;
- err = vfs_statfs(s->s_root, &sbuf);
+ err = vfs_statfs(s->s_root, NULL, &sbuf);
drop_super(s);
if (err)
goto out;
@@ -186,12 +186,13 @@ struct hpux_statfs {
int16_t f_pad;
};
-static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf)
+static int vfs_statfs_hpux(struct dentry *dentry, struct vfsmount *mnt,
+ struct hpux_statfs *buf)
{
struct kstatfs st;
int retval;
- retval = vfs_statfs(dentry, &st);
+ retval = vfs_statfs(dentry, mnt, &st);
if (retval)
return retval;
@@ -219,7 +220,7 @@ asmlinkage long hpux_statfs(const char _
error = user_path_walk(path, &nd);
if (!error) {
struct hpux_statfs tmp;
- error = vfs_statfs_hpux(nd.dentry, &tmp);
+ error = vfs_statfs_hpux(nd.dentry, nd.mnt, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
path_release(&nd);
@@ -237,7 +238,7 @@ asmlinkage long hpux_fstatfs(unsigned in
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs_hpux(file->f_path.dentry, &tmp);
+ error = vfs_statfs_hpux(file->f_path.dentry, file->f_path.mnt, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
fput(file);
Index: linux-2.6-apparmor/arch/sparc64/solaris/fs.c
===================================================================
--- linux-2.6-apparmor.orig/arch/sparc64/solaris/fs.c
+++ linux-2.6-apparmor/arch/sparc64/solaris/fs.c
@@ -361,15 +361,12 @@ static int report_statvfs(struct vfsmoun
int error;
struct sol_statvfs __user *ss = A(buf);
- error = vfs_statfs(mnt->mnt_root, &s);
+ error = vfs_statfs(mnt->mnt_root, mnt, &s);
if (!error) {
const char *p = mnt->mnt_sb->s_type->name;
- int i = 0;
int j = strlen (p);
if (j > 15) j = 15;
- if (IS_RDONLY(inode)) i = 1;
- if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
if (!sysv_valid_dev(inode->i_sb->s_dev))
return -EOVERFLOW;
if (put_user (s.f_bsize, &ss->f_bsize) ||
@@ -384,7 +381,8 @@ static int report_statvfs(struct vfsmoun
__copy_to_user (ss->f_basetype,p,j) ||
__put_user (0, (char __user *)&ss->f_basetype[j]) ||
__put_user (s.f_namelen, &ss->f_namemax) ||
- __put_user (i, &ss->f_flag) ||
+ __put_user (s.s_flag & (ST_RDONLY | ST_NOSUID),
+ &ss->f_flag) ||
__clear_user (&ss->f_fstr, 32))
return -EFAULT;
}
@@ -397,15 +395,12 @@ static int report_statvfs64(struct vfsmo
int error;
struct sol_statvfs64 __user *ss = A(buf);
- error = vfs_statfs(mnt->mnt_root, &s);
+ error = vfs_statfs(mnt->mnt_root, mnt, &s);
if (!error) {
const char *p = mnt->mnt_sb->s_type->name;
- int i = 0;
int j = strlen (p);
if (j > 15) j = 15;
- if (IS_RDONLY(inode)) i = 1;
- if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
if (!sysv_valid_dev(inode->i_sb->s_dev))
return -EOVERFLOW;
if (put_user (s.f_bsize, &ss->f_bsize) ||
@@ -420,7 +415,8 @@ static int report_statvfs64(struct vfsmo
__copy_to_user (ss->f_basetype,p,j) ||
__put_user (0, (char __user *)&ss->f_basetype[j]) ||
__put_user (s.f_namelen, &ss->f_namemax) ||
- __put_user (i, &ss->f_flag) ||
+ __put_user (s.s_flag & (ST_RDONLY | ST_NOSUID),
+ &ss->f_flag) ||
__clear_user (&ss->f_fstr, 32))
return -EFAULT;
}
Index: linux-2.6-apparmor/include/asm-arm/statfs.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-arm/statfs.h
+++ linux-2.6-apparmor/include/asm-arm/statfs.h
@@ -17,7 +17,8 @@ struct statfs {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
};
/*
@@ -36,7 +37,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
} __attribute__ ((packed,aligned(4)));
#endif
Index: linux-2.6-apparmor/include/asm-ia64/compat.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-ia64/compat.h
+++ linux-2.6-apparmor/include/asm-ia64/compat.h
@@ -102,7 +102,8 @@ struct compat_statfs {
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_frsize;
- int f_spare[5];
+ int f_flag;
+ int f_spare[4];
};
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
Index: linux-2.6-apparmor/include/asm-ia64/statfs.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-ia64/statfs.h
+++ linux-2.6-apparmor/include/asm-ia64/statfs.h
@@ -27,7 +27,8 @@ struct statfs {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
@@ -42,7 +43,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
struct compat_statfs64 {
@@ -56,7 +58,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
} __attribute__((packed));
#endif /* _ASM_IA64_STATFS_H */
Index: linux-2.6-apparmor/include/asm-parisc/compat.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-parisc/compat.h
+++ linux-2.6-apparmor/include/asm-parisc/compat.h
@@ -102,7 +102,8 @@ struct compat_statfs {
__kernel_fsid_t f_fsid;
s32 f_namelen;
s32 f_frsize;
- s32 f_spare[5];
+ s32 f_flag;
+ s32 f_spare[4];
};
struct compat_sigcontext {
Index: linux-2.6-apparmor/include/asm-parisc/statfs.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-parisc/statfs.h
+++ linux-2.6-apparmor/include/asm-parisc/statfs.h
@@ -24,7 +24,8 @@ struct statfs {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
struct statfs64 {
@@ -38,7 +39,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
struct compat_statfs64 {
@@ -52,7 +54,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
};
#endif
Index: linux-2.6-apparmor/include/asm-powerpc/compat.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-powerpc/compat.h
+++ linux-2.6-apparmor/include/asm-powerpc/compat.h
@@ -97,7 +97,8 @@ struct compat_statfs {
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_frsize;
- int f_spare[5];
+ int f_flag;
+ int f_spare[4];
};
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
Index: linux-2.6-apparmor/include/asm-powerpc/statfs.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-powerpc/statfs.h
+++ linux-2.6-apparmor/include/asm-powerpc/statfs.h
@@ -26,7 +26,8 @@ struct statfs {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
struct statfs64 {
@@ -40,7 +41,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
struct compat_statfs64 {
@@ -54,7 +56,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
};
#endif /* ! __powerpc64__ */
#endif
Index: linux-2.6-apparmor/include/asm-s390/compat.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-s390/compat.h
+++ linux-2.6-apparmor/include/asm-s390/compat.h
@@ -127,7 +127,8 @@ struct compat_statfs {
compat_fsid_t f_fsid;
s32 f_namelen;
s32 f_frsize;
- s32 f_spare[6];
+ s32 f_flag;
+ s32 f_spare[5];
};
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
Index: linux-2.6-apparmor/include/asm-s390/statfs.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-s390/statfs.h
+++ linux-2.6-apparmor/include/asm-s390/statfs.h
@@ -36,7 +36,8 @@ struct statfs {
__kernel_fsid_t f_fsid;
int f_namelen;
int f_frsize;
- int f_spare[5];
+ int f_flag;
+ int f_spare[4];
};
struct statfs64 {
@@ -50,7 +51,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid;
int f_namelen;
int f_frsize;
- int f_spare[5];
+ int f_flag;
+ int f_spare[4];
};
struct compat_statfs64 {
@@ -64,7 +66,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
};
#endif /* __s390x__ */
Index: linux-2.6-apparmor/include/asm-sparc64/compat.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-sparc64/compat.h
+++ linux-2.6-apparmor/include/asm-sparc64/compat.h
@@ -131,7 +131,8 @@ struct compat_statfs {
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_frsize;
- int f_spare[5];
+ int f_flag;
+ int f_spare[4];
};
#define COMPAT_RLIM_INFINITY 0x7fffffff
Index: linux-2.6-apparmor/include/asm-sparc64/statfs.h
===================================================================
--- linux-2.6-apparmor.orig/include/asm-sparc64/statfs.h
+++ linux-2.6-apparmor/include/asm-sparc64/statfs.h
@@ -21,7 +21,8 @@ struct statfs {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
struct statfs64 {
@@ -35,7 +36,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
struct compat_statfs64 {
@@ -49,7 +51,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
};
#endif

View file

@ -1,370 +0,0 @@
---
fs/compat.c | 13 +++++-----
fs/ecryptfs/super.c | 5 +++-
fs/nfsd/nfs4xdr.c | 2 -
fs/nfsd/vfs.c | 2 -
fs/open.c | 53 ++++++++++++++++++++++++++++++++++---------
fs/super.c | 2 -
include/asm-generic/statfs.h | 9 ++++---
include/asm-x86_64/compat.h | 3 +-
include/asm-x86_64/statfs.h | 9 ++++---
include/linux/fs.h | 2 -
include/linux/statfs.h | 13 +++++++++-
kernel/acct.c | 2 -
12 files changed, 84 insertions(+), 31 deletions(-)
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -194,7 +194,7 @@ static int put_compat_statfs(struct comp
__put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
__put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
__put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
- __put_user(0, &ubuf->f_spare[0]) ||
+ __put_user(kbuf->f_flag, &ubuf->f_flag) ||
__put_user(0, &ubuf->f_spare[1]) ||
__put_user(0, &ubuf->f_spare[2]) ||
__put_user(0, &ubuf->f_spare[3]) ||
@@ -215,7 +215,7 @@ asmlinkage long compat_sys_statfs(const
error = user_path_walk(path, &nd);
if (!error) {
struct kstatfs tmp;
- error = vfs_statfs(nd.dentry, &tmp);
+ error = vfs_statfs(nd.dentry, nd.mnt, &tmp);
if (!error)
error = put_compat_statfs(buf, &tmp);
path_release(&nd);
@@ -233,7 +233,7 @@ asmlinkage long compat_sys_fstatfs(unsig
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs(file->f_path.dentry, &tmp);
+ error = vfs_statfs(file->f_path.dentry, file->f_path.mnt, &tmp);
if (!error)
error = put_compat_statfs(buf, &tmp);
fput(file);
@@ -267,7 +267,8 @@ static int put_compat_statfs64(struct co
__put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
__put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
__put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
- __put_user(kbuf->f_frsize, &ubuf->f_frsize))
+ __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
+ __put_user(kbuf->f_flag, &ubuf->f_flag))
return -EFAULT;
return 0;
}
@@ -283,7 +284,7 @@ asmlinkage long compat_sys_statfs64(cons
error = user_path_walk(path, &nd);
if (!error) {
struct kstatfs tmp;
- error = vfs_statfs(nd.dentry, &tmp);
+ error = vfs_statfs(nd.dentry, nd.mnt, &tmp);
if (!error)
error = put_compat_statfs64(buf, &tmp);
path_release(&nd);
@@ -304,7 +305,7 @@ asmlinkage long compat_sys_fstatfs64(uns
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs(file->f_path.dentry, &tmp);
+ error = vfs_statfs(file->f_path.dentry, file->f_path.mnt, &tmp);
if (!error)
error = put_compat_statfs64(buf, &tmp);
fput(file);
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -119,7 +119,10 @@ static void ecryptfs_put_super(struct su
*/
static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
- return vfs_statfs(ecryptfs_dentry_to_lower(dentry), buf);
+ struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+
+ return vfs_statfs(lower_dentry, lower_mnt, buf);
}
/**
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1457,7 +1457,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
(bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
FATTR4_WORD1_SPACE_TOTAL))) {
- err = vfs_statfs(dentry, &statfs);
+ err = vfs_statfs(dentry, exp->ex_mnt, &statfs);
if (err)
goto out_nfserr;
}
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1767,7 +1767,7 @@ __be32
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
{
__be32 err = fh_verify(rqstp, fhp, 0, MAY_NOP);
- if (!err && vfs_statfs(fhp->fh_dentry,stat))
+ if (!err && vfs_statfs(fhp->fh_dentry, fhp->fh_export->ex_mnt, stat))
err = nfserr_io;
return err;
}
--- a/fs/open.c
+++ b/fs/open.c
@@ -28,7 +28,7 @@
#include <linux/rcupdate.h>
#include <linux/audit.h>
-int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+int vfs_statfs(struct dentry *dentry, struct vfsmount *mnt, struct kstatfs *buf)
{
int retval = -ENODEV;
@@ -40,8 +40,35 @@ int vfs_statfs(struct dentry *dentry, st
if (retval)
return retval;
retval = dentry->d_sb->s_op->statfs(dentry, buf);
- if (retval == 0 && buf->f_frsize == 0)
- buf->f_frsize = buf->f_bsize;
+ if (retval == 0) {
+ unsigned long f_flag = ST_IN_USE;
+ unsigned long x;
+
+ if (buf->f_frsize == 0)
+ buf->f_frsize = buf->f_bsize;
+
+ x = dentry->d_inode->i_sb->s_flags;
+ if (x & MS_RDONLY)
+ f_flag |= ST_RDONLY;
+ if (x & MS_SYNCHRONOUS)
+ f_flag |= ST_SYNCHRONOUS;
+ if (x & MS_MANDLOCK)
+ f_flag |= ST_MANDLOCK;
+
+ if (mnt) {
+ int x = mnt->mnt_flags;
+
+ if (x & MNT_NOSUID)
+ f_flag |= ST_NOSUID;
+ if (x & MNT_NODEV)
+ f_flag |= ST_NODEV;
+ if (x & MNT_NOATIME)
+ f_flag |= ST_NOATIME;
+ if (x & MNT_NODIRATIME)
+ f_flag |= ST_NODIRATIME;
+ }
+ buf->f_flag = f_flag;
+ }
}
}
return retval;
@@ -49,12 +76,13 @@ int vfs_statfs(struct dentry *dentry, st
EXPORT_SYMBOL(vfs_statfs);
-static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf)
+static int vfs_statfs_native(struct dentry *dentry, struct vfsmount *mnt,
+ struct statfs *buf)
{
struct kstatfs st;
int retval;
- retval = vfs_statfs(dentry, &st);
+ retval = vfs_statfs(dentry, mnt, &st);
if (retval)
return retval;
@@ -87,17 +115,19 @@ static int vfs_statfs_native(struct dent
buf->f_fsid = st.f_fsid;
buf->f_namelen = st.f_namelen;
buf->f_frsize = st.f_frsize;
+ buf->f_flag = st.f_flag;
memset(buf->f_spare, 0, sizeof(buf->f_spare));
}
return 0;
}
-static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
+static int vfs_statfs64(struct dentry *dentry, struct vfsmount *mnt,
+ struct statfs64 *buf)
{
struct kstatfs st;
int retval;
- retval = vfs_statfs(dentry, &st);
+ retval = vfs_statfs(dentry, mnt, &st);
if (retval)
return retval;
@@ -114,6 +144,7 @@ static int vfs_statfs64(struct dentry *d
buf->f_fsid = st.f_fsid;
buf->f_namelen = st.f_namelen;
buf->f_frsize = st.f_frsize;
+ buf->f_flag = st.f_flag;
memset(buf->f_spare, 0, sizeof(buf->f_spare));
}
return 0;
@@ -127,7 +158,7 @@ asmlinkage long sys_statfs(const char __
error = user_path_walk(path, &nd);
if (!error) {
struct statfs tmp;
- error = vfs_statfs_native(nd.dentry, &tmp);
+ error = vfs_statfs_native(nd.dentry, nd.mnt, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
path_release(&nd);
@@ -146,7 +177,7 @@ asmlinkage long sys_statfs64(const char
error = user_path_walk(path, &nd);
if (!error) {
struct statfs64 tmp;
- error = vfs_statfs64(nd.dentry, &tmp);
+ error = vfs_statfs64(nd.dentry, nd.mnt, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
path_release(&nd);
@@ -165,7 +196,7 @@ asmlinkage long sys_fstatfs(unsigned int
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs_native(file->f_path.dentry, &tmp);
+ error = vfs_statfs_native(file->f_path.dentry, file->f_path.mnt, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
fput(file);
@@ -186,7 +217,7 @@ asmlinkage long sys_fstatfs64(unsigned i
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs64(file->f_path.dentry, &tmp);
+ error = vfs_statfs64(file->f_path.dentry, file->f_path.mnt, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
fput(file);
--- a/fs/super.c
+++ b/fs/super.c
@@ -542,7 +542,7 @@ asmlinkage long sys_ustat(unsigned dev,
s = user_get_super(new_decode_dev(dev));
if (s == NULL)
goto out;
- err = vfs_statfs(s->s_root, &sbuf);
+ err = vfs_statfs(s->s_root, NULL, &sbuf);
drop_super(s);
if (err)
goto out;
--- a/include/asm-generic/statfs.h
+++ b/include/asm-generic/statfs.h
@@ -17,7 +17,8 @@ struct statfs {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
};
struct statfs64 {
@@ -31,7 +32,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
};
struct compat_statfs64 {
@@ -45,7 +47,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
};
#endif
--- a/include/asm-x86_64/compat.h
+++ b/include/asm-x86_64/compat.h
@@ -104,7 +104,8 @@ struct compat_statfs {
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_frsize;
- int f_spare[5];
+ int f_flag;
+ int f_spare[4];
};
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
--- a/include/asm-x86_64/statfs.h
+++ b/include/asm-x86_64/statfs.h
@@ -24,7 +24,8 @@ struct statfs {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
struct statfs64 {
@@ -38,7 +39,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ long f_flag;
+ long f_spare[4];
};
struct compat_statfs64 {
@@ -52,7 +54,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
- __u32 f_spare[5];
+ __u32 f_flag;
+ __u32 f_spare[4];
} __attribute__((packed));
#endif
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1408,7 +1408,7 @@ extern struct vfsmount *copy_tree(struct
extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
struct vfsmount *);
-extern int vfs_statfs(struct dentry *, struct kstatfs *);
+extern int vfs_statfs(struct dentry *, struct vfsmount *, struct kstatfs *);
/* /sys/fs */
extern struct subsystem fs_subsys;
--- a/include/linux/statfs.h
+++ b/include/linux/statfs.h
@@ -16,7 +16,18 @@ struct kstatfs {
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
- long f_spare[5];
+ unsigned long f_flag;
+ long f_spare[4];
};
+#define ST_RDONLY 1
+#define ST_NOSUID 2
+#define ST_NODEV 4
+#define ST_NOEXEC 8
+#define ST_SYNCHRONOUS 16
+#define ST_MANDLOCK 64
+#define ST_NOATIME 1024
+#define ST_NODIRATIME 2048
+#define ST_IN_USE (1 << 31)
+
#endif
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -118,7 +118,7 @@ static int check_free_space(struct file
spin_unlock(&acct_globals.lock);
/* May block */
- if (vfs_statfs(file->f_path.dentry, &sbuf))
+ if (vfs_statfs(file->f_path.dentry, file->f_path.mnt, &sbuf))
return res;
suspend = sbuf.f_blocks * SUSPEND;
resume = sbuf.f_blocks * RESUME;

View file

@ -1,5 +0,0 @@
struct_path-nameidata.diff
struct_path-vfs_getattr.diff
struct_path-getattr-iop.diff
struct_path-security-getattr.diff
struct_path-nfsfh.diff

View file

@ -1,504 +0,0 @@
Index: linux-2.6/fs/9p/vfs_inode.c
===================================================================
--- linux-2.6.orig/fs/9p/vfs_inode.c
+++ linux-2.6/fs/9p/vfs_inode.c
@@ -824,16 +824,15 @@ Release_lock:
/**
* v9fs_vfs_getattr - retrieve file metadata
- * @mnt - mount information
- * @dentry - file to get attributes on
+ * @path - file to get attributes on
* @stat - metadata structure to populate
*
*/
static int
-v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+v9fs_vfs_getattr(struct path *path, struct kstat *stat)
{
+ struct dentry *dentry = path->dentry;
struct v9fs_fcall *fcall = NULL;
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
struct v9fs_fid *fid = v9fs_fid_clone(dentry);
Index: linux-2.6/fs/afs/inode.c
===================================================================
--- linux-2.6.orig/fs/afs/inode.c
+++ linux-2.6/fs/afs/inode.c
@@ -218,15 +218,13 @@ inline int afs_iget(struct super_block *
/*
* read the attributes of an inode
*/
-int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+int afs_inode_getattr(struct path *path, struct kstat *stat)
{
+ struct dentry *dentry = path->dentry;
+ struct inode *inode = dentry->d_inode;
struct afs_vnode *vnode;
- struct inode *inode;
int ret;
- inode = dentry->d_inode;
-
_enter("{ ino=%lu v=%lu }", inode->i_ino, inode->i_version);
vnode = AFS_FS_I(inode);
Index: linux-2.6/fs/afs/internal.h
===================================================================
--- linux-2.6.orig/fs/afs/internal.h
+++ linux-2.6/fs/afs/internal.h
@@ -82,8 +82,7 @@ extern int afs_cache_get_page_cookie(str
*/
extern int afs_iget(struct super_block *sb, struct afs_fid *fid,
struct inode **_inode);
-extern int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat);
+extern int afs_inode_getattr(struct path *path, struct kstat *stat);
extern void afs_clear_inode(struct inode *inode);
/*
Index: linux-2.6/fs/bad_inode.c
===================================================================
--- linux-2.6.orig/fs/bad_inode.c
+++ linux-2.6/fs/bad_inode.c
@@ -257,8 +257,7 @@ static int bad_inode_permission(struct i
return -EIO;
}
-static int bad_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+static int bad_inode_getattr(struct path *path, struct kstat *stat)
{
return -EIO;
}
Index: linux-2.6/fs/cifs/cifsfs.h
===================================================================
--- linux-2.6.orig/fs/cifs/cifsfs.h
+++ linux-2.6/fs/cifs/cifsfs.h
@@ -55,7 +55,7 @@ extern int cifs_rmdir(struct inode *, st
extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
struct dentry *);
extern int cifs_revalidate(struct dentry *);
-extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int cifs_getattr(struct path *, struct kstat *);
extern int cifs_setattr(struct dentry *, struct iattr *);
extern struct inode_operations cifs_file_inode_ops;
Index: linux-2.6/fs/cifs/inode.c
===================================================================
--- linux-2.6.orig/fs/cifs/inode.c
+++ linux-2.6/fs/cifs/inode.c
@@ -1091,9 +1091,9 @@ int cifs_revalidate(struct dentry *diren
return rc;
}
-int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+int cifs_getattr(struct path *path, struct kstat *stat)
{
+ struct dentry *dentry = path->dentry;
int err = cifs_revalidate(dentry);
if (!err) {
generic_fillattr(dentry->d_inode, stat);
Index: linux-2.6/fs/coda/inode.c
===================================================================
--- linux-2.6.orig/fs/coda/inode.c
+++ linux-2.6/fs/coda/inode.c
@@ -236,8 +236,9 @@ static void coda_clear_inode(struct inod
coda_cache_clear_inode(inode);
}
-int coda_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int coda_getattr(struct path *path, struct kstat *stat)
{
+ struct dentry *dentry = path->dentry;
int err = coda_revalidate_inode(dentry);
if (!err)
generic_fillattr(dentry->d_inode, stat);
Index: linux-2.6/fs/fat/file.c
===================================================================
--- linux-2.6.orig/fs/fat/file.c
+++ linux-2.6/fs/fat/file.c
@@ -303,8 +303,9 @@ void fat_truncate(struct inode *inode)
fat_flush_inodes(inode->i_sb, inode, NULL);
}
-int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int fat_getattr(struct path *path, struct kstat *stat)
{
+ struct dentry *dentry = path->dentry;
struct inode *inode = dentry->d_inode;
generic_fillattr(inode, stat);
stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size;
Index: linux-2.6/fs/fuse/dir.c
===================================================================
--- linux-2.6.orig/fs/fuse/dir.c
+++ linux-2.6/fs/fuse/dir.c
@@ -1067,11 +1067,11 @@ static int fuse_setattr(struct dentry *e
return err;
}
-static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
- struct kstat *stat)
+static int fuse_getattr(struct path *path, struct kstat *stat)
{
- struct inode *inode = entry->d_inode;
- int err = fuse_revalidate(entry);
+ struct dentry *dentry = path->dentry;
+ struct inode *inode = dentry->d_inode;
+ int err = fuse_revalidate(dentry);
if (!err)
generic_fillattr(inode, stat);
Index: linux-2.6/fs/gfs2/ops_inode.c
===================================================================
--- linux-2.6.orig/fs/gfs2/ops_inode.c
+++ linux-2.6/fs/gfs2/ops_inode.c
@@ -1001,9 +1001,9 @@ out:
* Returns: errno
*/
-static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+static int gfs2_getattr(struct path *path, struct kstat *stat)
{
+ struct dentry *dentry = path->dentry;
struct inode *inode = dentry->d_inode;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder gh;
Index: linux-2.6/fs/hostfs/hostfs_kern.c
===================================================================
--- linux-2.6.orig/fs/hostfs/hostfs_kern.c
+++ linux-2.6/fs/hostfs/hostfs_kern.c
@@ -873,10 +873,9 @@ int hostfs_setattr(struct dentry *dentry
return(inode_setattr(dentry->d_inode, attr));
}
-int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+int hostfs_getattr(struct path *path, struct kstat *stat)
{
- generic_fillattr(dentry->d_inode, stat);
+ generic_fillattr(path->dentry->d_inode, stat);
return(0);
}
Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c
+++ linux-2.6/fs/libfs.c
@@ -11,10 +11,9 @@
#include <asm/uaccess.h>
-int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+int simple_getattr(struct path *path, struct kstat *stat)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = path->dentry->d_inode;
generic_fillattr(inode, stat);
stat->blocks = inode->i_mapping->nrpages << (PAGE_CACHE_SHIFT - 9);
return 0;
Index: linux-2.6/fs/minix/inode.c
===================================================================
--- linux-2.6.orig/fs/minix/inode.c
+++ linux-2.6/fs/minix/inode.c
@@ -535,8 +535,9 @@ int minix_sync_inode(struct inode * inod
return err;
}
-int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int minix_getattr(struct path *path, struct kstat *stat)
{
+ struct dentry *dentry = path->dentry;
generic_fillattr(dentry->d_inode, stat);
if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size);
Index: linux-2.6/fs/minix/minix.h
===================================================================
--- linux-2.6.orig/fs/minix/minix.h
+++ linux-2.6/fs/minix/minix.h
@@ -55,7 +55,7 @@ extern int minix_new_block(struct inode
extern void minix_free_block(struct inode * inode, int block);
extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
-extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int minix_getattr(struct path *, struct kstat *);
extern void V2_minix_truncate(struct inode *);
extern void V1_minix_truncate(struct inode *);
Index: linux-2.6/fs/nfs/inode.c
===================================================================
--- linux-2.6.orig/fs/nfs/inode.c
+++ linux-2.6/fs/nfs/inode.c
@@ -415,9 +415,9 @@ static void nfs_wake_up_inode(struct ino
wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING);
}
-int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int nfs_getattr(struct path *path, struct kstat *stat)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = path->dentry->d_inode;
int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
int err;
@@ -433,8 +433,8 @@ int nfs_getattr(struct vfsmount *mnt, st
* - NFS never sets MS_NOATIME or MS_NODIRATIME so there is
* no point in checking those.
*/
- if ((mnt->mnt_flags & MNT_NOATIME) ||
- ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
+ if ((path->mnt->mnt_flags & MNT_NOATIME) ||
+ ((path->mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
need_atime = 0;
if (need_atime)
Index: linux-2.6/fs/ocfs2/file.c
===================================================================
--- linux-2.6.orig/fs/ocfs2/file.c
+++ linux-2.6/fs/ocfs2/file.c
@@ -935,10 +935,9 @@ bail:
return status;
}
-int ocfs2_getattr(struct vfsmount *mnt,
- struct dentry *dentry,
- struct kstat *stat)
+int ocfs2_getattr(struct path *path, struct kstat *stat)
{
+ struct dentry *dentry = path->dentry;
struct inode *inode = dentry->d_inode;
struct super_block *sb = dentry->d_inode->i_sb;
struct ocfs2_super *osb = sb->s_fs_info;
Index: linux-2.6/fs/ocfs2/file.h
===================================================================
--- linux-2.6.orig/fs/ocfs2/file.h
+++ linux-2.6/fs/ocfs2/file.h
@@ -46,8 +46,7 @@ int ocfs2_do_extend_allocation(struct oc
struct ocfs2_alloc_context *meta_ac,
enum ocfs2_alloc_restarted *reason);
int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
-int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat);
+int ocfs2_getattr(struct path *path, struct kstat *stat);
int ocfs2_permission(struct inode *inode, int mask,
struct nameidata *nd);
Index: linux-2.6/fs/proc/base.c
===================================================================
--- linux-2.6.orig/fs/proc/base.c
+++ linux-2.6/fs/proc/base.c
@@ -1045,9 +1045,9 @@ out_unlock:
return NULL;
}
-static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+static int pid_getattr(struct path *path, struct kstat *stat)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = path->dentry->d_inode;
struct task_struct *task;
generic_fillattr(inode, stat);
@@ -2379,9 +2379,9 @@ out_no_task:
return retval;
}
-static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+static int proc_task_getattr(struct path *path, struct kstat *stat)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = path->dentry->d_inode;
struct task_struct *p = get_proc_task(inode);
generic_fillattr(inode, stat);
Index: linux-2.6/fs/proc/generic.c
===================================================================
--- linux-2.6.orig/fs/proc/generic.c
+++ linux-2.6/fs/proc/generic.c
@@ -253,10 +253,9 @@ out:
return error;
}
-static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+static int proc_getattr(struct path *path, struct kstat *stat)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = path->dentry->d_inode;
struct proc_dir_entry *de = PROC_I(inode)->pde;
if (de && de->nlink)
inode->i_nlink = de->nlink;
Index: linux-2.6/fs/proc/root.c
===================================================================
--- linux-2.6.orig/fs/proc/root.c
+++ linux-2.6/fs/proc/root.c
@@ -92,10 +92,9 @@ void __init proc_root_init(void)
proc_bus = proc_mkdir("bus", NULL);
}
-static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
-)
+static int proc_root_getattr(struct path *path, struct kstat *stat)
{
- generic_fillattr(dentry->d_inode, stat);
+ generic_fillattr(path->dentry->d_inode, stat);
stat->nlink = proc_root.nlink + nr_processes();
return 0;
}
Index: linux-2.6/fs/smbfs/inode.c
===================================================================
--- linux-2.6.orig/fs/smbfs/inode.c
+++ linux-2.6/fs/smbfs/inode.c
@@ -653,8 +653,9 @@ smb_statfs(struct dentry *dentry, struct
return result;
}
-int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int smb_getattr(struct path *path, struct kstat *stat)
{
+ struct dentry *dentry = path->dentry;
int err = smb_revalidate_inode(dentry);
if (!err)
generic_fillattr(dentry->d_inode, stat);
Index: linux-2.6/fs/smbfs/proto.h
===================================================================
--- linux-2.6.orig/fs/smbfs/proto.h
+++ linux-2.6/fs/smbfs/proto.h
@@ -60,7 +60,7 @@ extern void smb_get_inode_attr(struct in
extern void smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr);
extern void smb_invalidate_inodes(struct smb_sb_info *server);
extern int smb_revalidate_inode(struct dentry *dentry);
-extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
+extern int smb_getattr(struct path *path, struct kstat *stat);
extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
/* file.c */
extern const struct address_space_operations smb_file_aops;
Index: linux-2.6/fs/stat.c
===================================================================
--- linux-2.6.orig/fs/stat.c
+++ linux-2.6/fs/stat.c
@@ -48,7 +48,7 @@ int vfs_getattr(struct path *path, struc
return retval;
if (inode->i_op->getattr)
- return inode->i_op->getattr(path->mnt, path->dentry, stat);
+ return inode->i_op->getattr(path, stat);
generic_fillattr(inode, stat);
return 0;
Index: linux-2.6/fs/sysv/itree.c
===================================================================
--- linux-2.6.orig/fs/sysv/itree.c
+++ linux-2.6/fs/sysv/itree.c
@@ -440,10 +440,10 @@ static unsigned sysv_nblocks(struct supe
return blocks;
}
-int sysv_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int sysv_getattr(struct path *path, struct kstat *stat)
{
- struct super_block *s = mnt->mnt_sb;
- generic_fillattr(dentry->d_inode, stat);
+ struct super_block *s = path->mnt->mnt_sb;
+ generic_fillattr(path->dentry->d_inode, stat);
stat->blocks = (s->s_blocksize / 512) * sysv_nblocks(s, stat->size);
stat->blksize = s->s_blocksize;
return 0;
Index: linux-2.6/fs/sysv/sysv.h
===================================================================
--- linux-2.6.orig/fs/sysv/sysv.h
+++ linux-2.6/fs/sysv/sysv.h
@@ -142,7 +142,7 @@ extern int sysv_write_inode(struct inode
extern int sysv_sync_inode(struct inode *);
extern int sysv_sync_file(struct file *, struct dentry *, int);
extern void sysv_set_inode(struct inode *, dev_t);
-extern int sysv_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int sysv_getattr(struct path *, struct kstat *);
extern int sysv_init_icache(void);
extern void sysv_destroy_icache(void);
Index: linux-2.6/fs/xfs/linux-2.6/xfs_iops.c
===================================================================
--- linux-2.6.orig/fs/xfs/linux-2.6/xfs_iops.c
+++ linux-2.6/fs/xfs/linux-2.6/xfs_iops.c
@@ -617,11 +617,10 @@ xfs_vn_permission(
STATIC int
xfs_vn_getattr(
- struct vfsmount *mnt,
- struct dentry *dentry,
+ struct path *path,
struct kstat *stat)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = path->dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
bhv_vattr_t vattr = { .va_mask = XFS_AT_STAT };
int error;
Index: linux-2.6/include/linux/coda_linux.h
===================================================================
--- linux-2.6.orig/include/linux/coda_linux.h
+++ linux-2.6/include/linux/coda_linux.h
@@ -40,7 +40,7 @@ int coda_flush(struct file *f, fl_owner_
int coda_release(struct inode *i, struct file *f);
int coda_permission(struct inode *inode, int mask, struct nameidata *nd);
int coda_revalidate_inode(struct dentry *);
-int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+int coda_getattr(struct path *, struct kstat *);
int coda_setattr(struct dentry *, struct iattr *);
/* global variables */
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1118,7 +1118,7 @@ struct inode_operations {
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, struct nameidata *);
int (*setattr) (struct dentry *, struct iattr *);
- int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
+ int (*getattr) (struct path *path, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
@@ -1850,7 +1850,7 @@ extern int dcache_dir_open(struct inode
extern int dcache_dir_close(struct inode *, struct file *);
extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
extern int dcache_readdir(struct file *, void *, filldir_t);
-extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int simple_getattr(struct path *, struct kstat *);
extern int simple_statfs(struct dentry *, struct kstatfs *);
extern int simple_link(struct dentry *, struct inode *, struct dentry *);
extern int simple_unlink(struct inode *, struct dentry *);
Index: linux-2.6/include/linux/msdos_fs.h
===================================================================
--- linux-2.6.orig/include/linux/msdos_fs.h
+++ linux-2.6/include/linux/msdos_fs.h
@@ -402,8 +402,7 @@ extern const struct file_operations fat_
extern struct inode_operations fat_file_inode_operations;
extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
extern void fat_truncate(struct inode *inode);
-extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat);
+extern int fat_getattr(struct path *path, struct kstat *stat);
/* fat/inode.c */
extern void fat_attach(struct inode *inode, loff_t i_pos);
Index: linux-2.6/include/linux/nfs_fs.h
===================================================================
--- linux-2.6.orig/include/linux/nfs_fs.h
+++ linux-2.6/include/linux/nfs_fs.h
@@ -297,7 +297,7 @@ extern struct inode *nfs_fhget(struct su
struct nfs_fattr *);
extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
-extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int nfs_getattr(struct path *, struct kstat *);
extern int nfs_permission(struct inode *, int, struct nameidata *);
extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *);
extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);

View file

@ -1,920 +0,0 @@
Index: linux-2.6/fs/nfsd/nfs2acl.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs2acl.c
+++ linux-2.6/fs/nfsd/nfs2acl.c
@@ -62,7 +62,7 @@ static __be32 nfsacld_proc_getacl(struct
if (acl == NULL) {
/* Solaris returns the inode's minimum ACL. */
- struct inode *inode = fh->fh_dentry->d_inode;
+ struct inode *inode = fh->fh_path.dentry->d_inode;
acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
}
resp->acl_access = acl;
@@ -220,7 +220,7 @@ static int nfsaclsvc_decode_accessargs(s
static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
struct nfsd3_getaclres *resp)
{
- struct dentry *dentry = resp->fh.fh_dentry;
+ struct dentry *dentry = resp->fh.fh_path.dentry;
struct inode *inode = dentry->d_inode;
struct kvec *head = rqstp->rq_res.head;
unsigned int base;
Index: linux-2.6/fs/nfsd/nfs3acl.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs3acl.c
+++ linux-2.6/fs/nfsd/nfs3acl.c
@@ -58,7 +58,7 @@ static __be32 nfsd3_proc_getacl(struct s
if (acl == NULL) {
/* Solaris returns the inode's minimum ACL. */
- struct inode *inode = fh->fh_dentry->d_inode;
+ struct inode *inode = fh->fh_path.dentry->d_inode;
acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
}
resp->acl_access = acl;
@@ -166,7 +166,7 @@ static int nfs3svc_decode_setaclargs(str
static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
struct nfsd3_getaclres *resp)
{
- struct dentry *dentry = resp->fh.fh_dentry;
+ struct dentry *dentry = resp->fh.fh_path.dentry;
p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
if (resp->status == 0 && dentry && dentry->d_inode) {
Index: linux-2.6/fs/nfsd/nfs3proc.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs3proc.c
+++ linux-2.6/fs/nfsd/nfs3proc.c
@@ -58,7 +58,6 @@ nfsd3_proc_getattr(struct svc_rqst *rqst
{
int err;
__be32 nfserr;
- struct path path;
dprintk("nfsd: GETATTR(3) %s\n",
SVCFH_fmt(&argp->fh));
@@ -68,9 +67,7 @@ nfsd3_proc_getattr(struct svc_rqst *rqst
if (nfserr)
RETURN_STATUS(nfserr);
- path.mnt = resp->fh.fh_export->ex_mnt;
- path.dentry = resp->fh.fh_dentry;
- err = vfs_getattr(&path, &resp->stat);
+ err = vfs_getattr(&resp->fh.fh_path, &resp->stat);
nfserr = nfserrno(err);
RETURN_STATUS(nfserr);
@@ -187,7 +184,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp,
rqstp->rq_vec, argp->vlen,
&resp->count);
if (nfserr == 0) {
- struct inode *inode = resp->fh.fh_dentry->d_inode;
+ struct inode *inode = resp->fh.fh_path.dentry->d_inode;
resp->eof = (argp->offset + resp->count) >= inode->i_size;
}
@@ -566,7 +563,7 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqst
* different read/write sizes for file systems known to have
* problems with large blocks */
if (nfserr == 0) {
- struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
+ struct super_block *sb = argp->fh.fh_path.dentry->d_inode->i_sb;
/* Note that we don't care for remote fs's here */
if (sb->s_magic == 0x4d44 /* MSDOS_SUPER_MAGIC */) {
@@ -602,7 +599,7 @@ nfsd3_proc_pathconf(struct svc_rqst * rq
nfserr = fh_verify(rqstp, &argp->fh, 0, MAY_NOP);
if (nfserr == 0) {
- struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
+ struct super_block *sb = argp->fh.fh_path.dentry->d_inode->i_sb;
/* Note that we don't care for remote fs's here */
switch (sb->s_magic) {
Index: linux-2.6/fs/nfsd/nfs3xdr.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs3xdr.c
+++ linux-2.6/fs/nfsd/nfs3xdr.c
@@ -153,7 +153,7 @@ static __be32 *
encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
struct kstat *stat)
{
- struct dentry *dentry = fhp->fh_dentry;
+ struct dentry *dentry = fhp->fh_path.dentry;
struct timespec time;
*p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
@@ -185,7 +185,7 @@ encode_fattr3(struct svc_rqst *rqstp, __
static __be32 *
encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
{
- struct inode *inode = fhp->fh_dentry->d_inode;
+ struct inode *inode = fhp->fh_path.dentry->d_inode;
/* Attributes to follow */
*p++ = xdr_one;
@@ -223,15 +223,13 @@ encode_saved_post_attr(struct svc_rqst *
static __be32 *
encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
{
- struct path path;
+ struct dentry *dentry = fhp->fh_path.dentry;
- path.dentry = fhp->fh_dentry;
- if (path.dentry && path.dentry->d_inode != NULL) {
+ if (dentry && dentry->d_inode != NULL) {
int err;
struct kstat stat;
- path.mnt = fhp->fh_export->ex_mnt;
- err = vfs_getattr(&path, &stat);
+ err = vfs_getattr(&fhp->fh_path, &stat);
if (!err) {
*p++ = xdr_one; /* attributes follow */
return encode_fattr3(rqstp, p, fhp, &stat);
@@ -254,7 +252,7 @@ nfs3svc_encode_post_op_attr(struct svc_r
static __be32 *
encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
{
- struct dentry *dentry = fhp->fh_dentry;
+ struct dentry *dentry = fhp->fh_path.dentry;
if (dentry && dentry->d_inode && fhp->fh_post_saved) {
if (fhp->fh_pre_saved) {
@@ -808,7 +806,7 @@ compose_entry_fh(struct nfsd3_readdirres
struct dentry *dparent, *dchild;
int rv = 0;
- dparent = cd->fh.fh_dentry;
+ dparent = cd->fh.fh_path.dentry;
exp = cd->fh.fh_export;
fh_init(fhp, NFS3_FHSIZE);
Index: linux-2.6/fs/nfsd/nfs4proc.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs4proc.c
+++ linux-2.6/fs/nfsd/nfs4proc.c
@@ -54,7 +54,7 @@ static inline void
fh_dup2(struct svc_fh *dst, struct svc_fh *src)
{
fh_put(dst);
- dget(src->fh_dentry);
+ dget(src->fh_path.dentry);
if (src->fh_export)
cache_get(&src->fh_export->h);
*dst = *src;
@@ -261,7 +261,7 @@ static __be32
nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct svc_fh **getfh)
{
- if (!cstate->current_fh.fh_dentry)
+ if (!cstate->current_fh.fh_path.dentry)
return nfserr_nofilehandle;
*getfh = &cstate->current_fh;
@@ -295,7 +295,7 @@ static __be32
nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
void *arg)
{
- if (!cstate->save_fh.fh_dentry)
+ if (!cstate->save_fh.fh_path.dentry)
return nfserr_restorefh;
fh_dup2(&cstate->current_fh, &cstate->save_fh);
@@ -306,7 +306,7 @@ static __be32
nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
void *arg)
{
- if (!cstate->current_fh.fh_dentry)
+ if (!cstate->current_fh.fh_path.dentry)
return nfserr_nofilehandle;
fh_dup2(&cstate->save_fh, &cstate->current_fh);
@@ -457,7 +457,7 @@ nfsd4_link(struct svc_rqst *rqstp, struc
{
__be32 status = nfserr_nofilehandle;
- if (!cstate->save_fh.fh_dentry)
+ if (!cstate->save_fh.fh_path.dentry)
return status;
status = nfsd_link(rqstp, &cstate->current_fh,
link->li_name, link->li_namelen, &cstate->save_fh);
@@ -477,7 +477,7 @@ nfsd4_lookupp(struct svc_rqst *rqstp, st
if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
&rqstp->rq_chandle)) != 0)
return ret;
- if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
+ if (tmp_fh.fh_path.dentry == cstate->current_fh.fh_path.dentry) {
fh_put(&tmp_fh);
return nfserr_noent;
}
@@ -583,7 +583,7 @@ nfsd4_rename(struct svc_rqst *rqstp, str
{
__be32 status = nfserr_nofilehandle;
- if (!cstate->save_fh.fh_dentry)
+ if (!cstate->save_fh.fh_path.dentry)
return status;
if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
& NFSEXP_NOSUBTREECHECK))
@@ -597,8 +597,8 @@ nfsd4_rename(struct svc_rqst *rqstp, str
if (status == nfserr_isdir)
status = nfserr_exist;
else if ((status == nfserr_notdir) &&
- (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
- S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
+ (S_ISDIR(cstate->save_fh.fh_path.dentry->d_inode->i_mode) &&
+ S_ISDIR(cstate->current_fh.fh_path.dentry->d_inode->i_mode)))
status = nfserr_exist;
else if (status == nfserr_symlink)
status = nfserr_notdir;
@@ -716,7 +716,7 @@ _nfsd4_verify(struct svc_rqst *rqstp, st
status = nfsd4_encode_fattr(&cstate->current_fh,
cstate->current_fh.fh_export,
- cstate->current_fh.fh_dentry, buf,
+ &cstate->current_fh.fh_path, buf,
&count, verify->ve_bmval,
rqstp);
@@ -876,7 +876,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
opdesc = &nfsd4_ops[op->opnum];
- if (!cstate->current_fh.fh_dentry) {
+ if (!cstate->current_fh.fh_path.dentry) {
if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
op->status = nfserr_nofilehandle;
goto encode_op;
Index: linux-2.6/fs/nfsd/nfs4state.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs4state.c
+++ linux-2.6/fs/nfsd/nfs4state.c
@@ -1286,7 +1286,7 @@ test_share(struct nfs4_stateid *stp, str
static __be32
nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
{
- struct inode *ino = current_fh->fh_dentry->d_inode;
+ struct inode *ino = current_fh->fh_path.dentry->d_inode;
struct nfs4_file *fp;
struct nfs4_stateid *stp;
__be32 ret;
@@ -1745,7 +1745,7 @@ __be32
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
struct nfs4_file *fp = NULL;
- struct inode *ino = current_fh->fh_dentry->d_inode;
+ struct inode *ino = current_fh->fh_path.dentry->d_inode;
struct nfs4_stateid *stp = NULL;
struct nfs4_delegation *dp = NULL;
__be32 status;
@@ -1969,7 +1969,7 @@ search_close_lru(u32 st_id, int flags)
static inline int
nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
{
- return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode;
+ return fhp->fh_path.dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode;
}
static int
@@ -2052,7 +2052,7 @@ nfs4_preprocess_stateid_op(struct svc_fh
struct nfs4_stateid *stp = NULL;
struct nfs4_delegation *dp = NULL;
stateid_t *stidp;
- struct inode *ino = current_fh->fh_dentry->d_inode;
+ struct inode *ino = current_fh->fh_path.dentry->d_inode;
__be32 status;
dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",
@@ -2253,8 +2253,8 @@ nfsd4_open_confirm(struct svc_rqst *rqst
struct nfs4_stateid *stp;
dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
- (int)cstate->current_fh.fh_dentry->d_name.len,
- cstate->current_fh.fh_dentry->d_name.name);
+ (int)cstate->current_fh.fh_path.dentry->d_name.len,
+ cstate->current_fh.fh_path.dentry->d_name.name);
status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
if (status)
@@ -2324,8 +2324,8 @@ nfsd4_open_downgrade(struct svc_rqst *rq
unsigned int share_access;
dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n",
- (int)cstate->current_fh.fh_dentry->d_name.len,
- cstate->current_fh.fh_dentry->d_name.name);
+ (int)cstate->current_fh.fh_path.dentry->d_name.len,
+ cstate->current_fh.fh_path.dentry->d_name.name);
if (!access_valid(od->od_share_access)
|| !deny_valid(od->od_share_deny))
@@ -2380,8 +2380,8 @@ nfsd4_close(struct svc_rqst *rqstp, stru
struct nfs4_stateid *stp;
dprintk("NFSD: nfsd4_close on file %.*s\n",
- (int)cstate->current_fh.fh_dentry->d_name.len,
- cstate->current_fh.fh_dentry->d_name.name);
+ (int)cstate->current_fh.fh_path.dentry->d_name.len,
+ cstate->current_fh.fh_path.dentry->d_name.name);
nfs4_lock_state();
/* check close_lru for replay */
@@ -2837,7 +2837,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, stru
goto out;
}
- inode = cstate->current_fh.fh_dentry->d_inode;
+ inode = cstate->current_fh.fh_path.dentry->d_inode;
locks_init_lock(&file_lock);
switch (lockt->lt_type) {
case NFS4_READ_LT:
@@ -2876,7 +2876,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, stru
* only the dentry:inode set.
*/
memset(&file, 0, sizeof (struct file));
- file.f_path.dentry = cstate->current_fh.fh_dentry;
+ file.f_path.dentry = cstate->current_fh.fh_path.dentry;
status = nfs_ok;
if (posix_test_lock(&file, &file_lock, &conflock)) {
Index: linux-2.6/fs/nfsd/nfs4xdr.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs4xdr.c
+++ linux-2.6/fs/nfsd/nfs4xdr.c
@@ -1424,7 +1424,7 @@ static __be32 fattr_handle_absent_fs(u32
*/
__be32
nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
- struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval,
+ struct path *path, __be32 *buffer, int *countp, u32 *bmval,
struct svc_rqst *rqstp)
{
u32 bmval0 = bmval[0];
@@ -1442,7 +1442,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
int err;
int aclsupport = 0;
struct nfs4_acl *acl = NULL;
- struct path path;
+ struct dentry *dentry = path->dentry;
BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
@@ -1454,9 +1454,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
goto out;
}
- path.mnt = exp->ex_mnt;
- path.dentry = dentry;
- err = vfs_getattr(&path, &stat);
+ err = vfs_getattr(path, &stat);
if (err)
goto out_nfserr;
if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
@@ -1839,28 +1837,29 @@ nfsd4_encode_dirent_fattr(struct nfsd4_r
const char *name, int namlen, __be32 *p, int *buflen)
{
struct svc_export *exp = cd->rd_fhp->fh_export;
- struct dentry *dentry;
+ struct path path;
__be32 nfserr;
- dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
- if (IS_ERR(dentry))
- return nfserrno(PTR_ERR(dentry));
+ path.dentry = lookup_one_len(name, cd->rd_fhp->fh_path.dentry, namlen);
+ if (IS_ERR(path.dentry))
+ return nfserrno(PTR_ERR(path.dentry));
exp_get(exp);
- if (d_mountpoint(dentry)) {
+ if (d_mountpoint(path.dentry)) {
int err;
- err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
+ err = nfsd_cross_mnt(cd->rd_rqstp, &path.dentry, &exp);
if (err) {
nfserr = nfserrno(err);
goto out_put;
}
}
- nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
+ path.mnt = exp->ex_mnt;
+ nfserr = nfsd4_encode_fattr(NULL, exp, &path, p, buflen, cd->rd_bmval,
cd->rd_rqstp);
out_put:
- dput(dentry);
+ dput(path.dentry);
exp_put(exp);
return nfserr;
}
@@ -2010,7 +2009,7 @@ nfsd4_encode_getattr(struct nfsd4_compou
return nfserr;
buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
- nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
+ nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, &fhp->fh_path,
resp->p, &buflen, getattr->ga_bmval,
resp->rqstp);
if (!nfserr)
@@ -2248,7 +2247,7 @@ nfsd4_encode_read(struct nfsd4_compoundr
if (nfserr)
return nfserr;
eof = (read->rd_offset + maxcount >=
- read->rd_fhp->fh_dentry->d_inode->i_size);
+ read->rd_fhp->fh_path.dentry->d_inode->i_size);
WRITE32(eof);
WRITE32(maxcount);
Index: linux-2.6/fs/nfsd/nfsfh.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfsfh.c
+++ linux-2.6/fs/nfsd/nfsfh.c
@@ -123,7 +123,7 @@ fh_verify(struct svc_rqst *rqstp, struct
/* keep this filehandle for possible reference when encoding attributes */
rqstp->rq_reffh = fh;
- if (!fhp->fh_dentry) {
+ if (!fhp->fh_path.dentry) {
__u32 *datap=NULL;
__u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */
int fileid_type;
@@ -238,7 +238,7 @@ fh_verify(struct svc_rqst *rqstp, struct
}
#endif
- fhp->fh_dentry = dentry;
+ fhp->fh_path.dentry = dentry;
fhp->fh_export = exp;
nfsd_nr_verified++;
} else {
@@ -246,7 +246,7 @@ fh_verify(struct svc_rqst *rqstp, struct
* (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well)
*/
dprintk("nfsd: fh_verify - just checking\n");
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
exp = fhp->fh_export;
/* Set user creds for this exportpoint; necessary even
* in the "just checking" case because this may be a
@@ -372,7 +372,7 @@ fh_compose(struct svc_fh *fhp, struct sv
if (ref_fh == fhp)
fh_put(ref_fh);
- if (fhp->fh_locked || fhp->fh_dentry) {
+ if (fhp->fh_locked || fhp->fh_path.dentry) {
printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
parent->d_name.name, dentry->d_name.name);
}
@@ -380,7 +380,8 @@ fh_compose(struct svc_fh *fhp, struct sv
printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
- fhp->fh_dentry = dget(dentry); /* our internal copy */
+ fhp->fh_path.mnt = exp->ex_mnt; /* FIXME: can this get released while we still keep the copy here? Probably not... */
+ fhp->fh_path.dentry = dget(dentry); /* our internal copy */
fhp->fh_export = exp;
cache_get(&exp->h);
@@ -459,10 +460,10 @@ fh_update(struct svc_fh *fhp)
struct dentry *dentry;
__u32 *datap;
- if (!fhp->fh_dentry)
+ if (!fhp->fh_path.dentry)
goto out_bad;
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
if (!dentry->d_inode)
goto out_negative;
if (fhp->fh_handle.fh_version != 1) {
@@ -498,11 +499,11 @@ out_negative:
void
fh_put(struct svc_fh *fhp)
{
- struct dentry * dentry = fhp->fh_dentry;
+ struct dentry * dentry = fhp->fh_path.dentry;
struct svc_export * exp = fhp->fh_export;
if (dentry) {
fh_unlock(fhp);
- fhp->fh_dentry = NULL;
+ fhp->fh_path.dentry = NULL;
dput(dentry);
#ifdef CONFIG_NFSD_V3
fhp->fh_pre_saved = 0;
Index: linux-2.6/fs/nfsd/nfsproc.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfsproc.c
+++ linux-2.6/fs/nfsd/nfsproc.c
@@ -39,25 +39,17 @@ nfsd_proc_null(struct svc_rqst *rqstp, v
static __be32
nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp)
{
- struct path path;
-
if (err)
return err;
- path.mnt = resp->fh.fh_export->ex_mnt;
- path.dentry = resp->fh.fh_dentry;
- return nfserrno(vfs_getattr(&path, &resp->stat));
+ return nfserrno(vfs_getattr(&resp->fh.fh_path, &resp->stat));
}
static __be32
nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp)
{
- struct path path;
-
if (err)
return err;
- path.mnt = resp->fh.fh_export->ex_mnt;
- path.dentry = resp->fh.fh_dentry;
- return nfserrno(vfs_getattr(&path, &resp->stat));
+ return nfserrno(vfs_getattr(&resp->fh.fh_path, &resp->stat));
}
/*
* Get a file's attributes
@@ -143,7 +135,6 @@ static __be32
nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
struct nfsd_readres *resp)
{
- struct path path;
__be32 nfserr;
dprintk("nfsd: READ %s %d bytes at %d\n",
@@ -172,9 +163,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, s
if (nfserr)
return nfserr;
- path.mnt = resp->fh.fh_export->ex_mnt;
- path.dentry = resp->fh.fh_dentry;
- return nfserrno(vfs_getattr(&path, &resp->stat));
+ return nfserrno(vfs_getattr(&resp->fh.fh_path, &resp->stat));
}
/*
@@ -236,7 +225,7 @@ nfsd_proc_create(struct svc_rqst *rqstp,
if (isdotent(argp->name, argp->len))
goto done;
fh_lock_nested(dirfhp, I_MUTEX_PARENT);
- dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
+ dchild = lookup_one_len(argp->name, dirfhp->fh_path.dentry, argp->len);
if (IS_ERR(dchild)) {
nfserr = nfserrno(PTR_ERR(dchild));
goto out_unlock;
@@ -254,14 +243,14 @@ nfsd_proc_create(struct svc_rqst *rqstp,
* whether the file exists or not. Time to bail ...
*/
nfserr = nfserr_acces;
- if (!newfhp->fh_dentry) {
+ if (!newfhp->fh_path.dentry) {
printk(KERN_WARNING
"nfsd_proc_create: file handle not verified\n");
goto out_unlock;
}
}
- inode = newfhp->fh_dentry->d_inode;
+ inode = newfhp->fh_path.dentry->d_inode;
/* Unfudge the mode bits */
if (attr->ia_valid & ATTR_MODE) {
@@ -286,9 +275,10 @@ nfsd_proc_create(struct svc_rqst *rqstp,
* echo thing > device-special-file-or-pipe
* by doing a CREATE with type==0
*/
- nfserr = nfsd_permission(newfhp->fh_export,
- newfhp->fh_dentry,
- MAY_WRITE|MAY_LOCAL_ACCESS);
+ nfserr = nfsd_permission(
+ newfhp->fh_export,
+ newfhp->fh_path.dentry,
+ MAY_WRITE|MAY_LOCAL_ACCESS);
if (nfserr && nfserr != nfserr_rofs)
goto out_unlock;
}
@@ -448,7 +438,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp,
dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
- if (resp->fh.fh_dentry) {
+ if (resp->fh.fh_path.dentry) {
printk(KERN_WARNING
"nfsd_proc_mkdir: response already verified??\n");
}
Index: linux-2.6/fs/nfsd/nfsxdr.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfsxdr.c
+++ linux-2.6/fs/nfsd/nfsxdr.c
@@ -150,7 +150,7 @@ static __be32 *
encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
struct kstat *stat)
{
- struct dentry *dentry = fhp->fh_dentry;
+ struct dentry *dentry = fhp->fh_path.dentry;
int type;
struct timespec time;
@@ -193,11 +193,8 @@ encode_fattr(struct svc_rqst *rqstp, __b
__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
{
struct kstat stat;
- struct path path;
- path.mnt = fhp->fh_export->ex_mnt;
- path.dentry = fhp->fh_dentry;
- vfs_getattr(&path, &stat);
+ vfs_getattr(&fhp->fh_path, &stat);
return encode_fattr(rqstp, p, fhp, &stat);
}
Index: linux-2.6/fs/nfsd/vfs.c
===================================================================
--- linux-2.6.orig/fs/nfsd/vfs.c
+++ linux-2.6/fs/nfsd/vfs.c
@@ -165,7 +165,7 @@ nfsd_lookup(struct svc_rqst *rqstp, stru
if (err)
return err;
- dparent = fhp->fh_dentry;
+ dparent = fhp->fh_path.dentry;
exp = fhp->fh_export;
exp_get(exp);
@@ -268,7 +268,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str
if (err)
goto out;
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
inode = dentry->d_inode;
/* Ignore any mode updates on symlinks */
@@ -438,7 +438,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
if (error)
goto out;
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
inode = dentry->d_inode;
if (S_ISDIR(inode->i_mode))
flags = NFS4_ACL_DIR;
@@ -588,7 +588,7 @@ nfsd_access(struct svc_rqst *rqstp, stru
goto out;
export = fhp->fh_export;
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
if (S_ISREG(dentry->d_inode->i_mode))
map = nfs3_regaccess;
@@ -659,7 +659,7 @@ nfsd_open(struct svc_rqst *rqstp, struct
if (err)
goto out;
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
inode = dentry->d_inode;
/* Disallow write access to files with the append-only bit set
@@ -1016,7 +1016,7 @@ nfsd_read(struct svc_rqst *rqstp, struct
__be32 err;
if (file) {
- err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+ err = nfsd_permission(fhp->fh_export, fhp->fh_path.dentry,
MAY_READ|MAY_OWNER_OVERRIDE);
if (err)
goto out;
@@ -1045,7 +1045,7 @@ nfsd_write(struct svc_rqst *rqstp, struc
__be32 err = 0;
if (file) {
- err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+ err = nfsd_permission(fhp->fh_export, fhp->fh_path.dentry,
MAY_WRITE|MAY_OWNER_OVERRIDE);
if (err)
goto out;
@@ -1128,7 +1128,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
if (err)
goto out;
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
dirp = dentry->d_inode;
err = nfserr_notdir;
@@ -1138,7 +1138,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
* Check whether the response file handle has been verified yet.
* If it has, the parent directory should already be locked.
*/
- if (!resfhp->fh_dentry) {
+ if (!resfhp->fh_path.dentry) {
/* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
fh_lock_nested(fhp, I_MUTEX_PARENT);
dchild = lookup_one_len(fname, dentry, flen);
@@ -1150,7 +1150,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
goto out;
} else {
/* called from nfsd_proc_create */
- dchild = dget(resfhp->fh_dentry);
+ dchild = dget(resfhp->fh_path.dentry);
if (!fhp->fh_locked) {
/* not actually possible */
printk(KERN_ERR
@@ -1258,7 +1258,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
if (err)
goto out;
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
dirp = dentry->d_inode;
/* Get all the sanity checks out of the way before
@@ -1391,7 +1391,7 @@ nfsd_readlink(struct svc_rqst *rqstp, st
if (err)
goto out;
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
inode = dentry->d_inode;
err = nfserr_inval;
@@ -1446,7 +1446,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
if (err)
goto out;
fh_lock(fhp);
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
dnew = lookup_one_len(fname, dentry, flen);
host_err = PTR_ERR(dnew);
if (IS_ERR(dnew))
@@ -1516,7 +1516,7 @@ nfsd_link(struct svc_rqst *rqstp, struct
goto out;
fh_lock_nested(ffhp, I_MUTEX_PARENT);
- ddir = ffhp->fh_dentry;
+ ddir = ffhp->fh_path.dentry;
dirp = ddir->d_inode;
dnew = lookup_one_len(name, ddir, len);
@@ -1524,7 +1524,7 @@ nfsd_link(struct svc_rqst *rqstp, struct
if (IS_ERR(dnew))
goto out_nfserr;
- dold = tfhp->fh_dentry;
+ dold = tfhp->fh_path.dentry;
dest = dold->d_inode;
host_err = vfs_link(dold, dirp, dnew);
@@ -1572,10 +1572,10 @@ nfsd_rename(struct svc_rqst *rqstp, stru
if (err)
goto out;
- fdentry = ffhp->fh_dentry;
+ fdentry = ffhp->fh_path.dentry;
fdir = fdentry->d_inode;
- tdentry = tfhp->fh_dentry;
+ tdentry = tfhp->fh_path.dentry;
tdir = tdentry->d_inode;
err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
@@ -1668,7 +1668,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
goto out;
fh_lock_nested(fhp, I_MUTEX_PARENT);
- dentry = fhp->fh_dentry;
+ dentry = fhp->fh_path.dentry;
dirp = dentry->d_inode;
rdentry = lookup_one_len(fname, dentry, flen);
@@ -1765,7 +1765,7 @@ __be32
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
{
__be32 err = fh_verify(rqstp, fhp, 0, MAY_NOP);
- if (!err && vfs_statfs(fhp->fh_dentry,stat))
+ if (!err && vfs_statfs(fhp->fh_path.dentry,stat))
err = nfserr_io;
return err;
}
@@ -1904,7 +1904,7 @@ nfsd_racache_init(int cache_size)
struct posix_acl *
nfsd_get_posix_acl(struct svc_fh *fhp, int type)
{
- struct inode *inode = fhp->fh_dentry->d_inode;
+ struct inode *inode = fhp->fh_path.dentry->d_inode;
char *name;
void *value = NULL;
ssize_t size;
@@ -1924,7 +1924,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
return ERR_PTR(-EOPNOTSUPP);
}
- size = nfsd_getxattr(fhp->fh_dentry, name, &value);
+ size = nfsd_getxattr(fhp->fh_path.dentry, name, &value);
if (size < 0)
return ERR_PTR(size);
@@ -1936,7 +1936,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
int
nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
{
- struct inode *inode = fhp->fh_dentry->d_inode;
+ struct inode *inode = fhp->fh_path.dentry->d_inode;
char *name;
void *value = NULL;
size_t size;
@@ -1969,12 +1969,12 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
size = 0;
if (size)
- error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
+ error = vfs_setxattr(fhp->fh_path.dentry, name, value, size, 0);
else {
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
error = 0;
else {
- error = vfs_removexattr(fhp->fh_dentry, name);
+ error = vfs_removexattr(fhp->fh_path.dentry, name);
if (error == -ENODATA)
error = 0;
}
Index: linux-2.6/include/linux/nfsd/nfsfh.h
===================================================================
--- linux-2.6.orig/include/linux/nfsd/nfsfh.h
+++ linux-2.6/include/linux/nfsd/nfsfh.h
@@ -134,7 +134,7 @@ static inline ino_t u32_to_ino_t(__u32 u
*/
typedef struct svc_fh {
struct knfsd_fh fh_handle; /* FH data */
- struct dentry * fh_dentry; /* validated dentry */
+ struct path fh_path; /* validated path */
struct svc_export * fh_export; /* export pointer */
int fh_maxsize; /* max size for fh_handle */
@@ -217,7 +217,7 @@ void fh_put(struct svc_fh *);
static __inline__ struct svc_fh *
fh_copy(struct svc_fh *dst, struct svc_fh *src)
{
- WARN_ON(src->fh_dentry || src->fh_locked);
+ WARN_ON(src->fh_path.dentry || src->fh_locked);
*dst = *src;
return dst;
@@ -240,7 +240,7 @@ fill_pre_wcc(struct svc_fh *fhp)
{
struct inode *inode;
- inode = fhp->fh_dentry->d_inode;
+ inode = fhp->fh_path.dentry->d_inode;
if (!fhp->fh_pre_saved) {
fhp->fh_pre_mtime = inode->i_mtime;
fhp->fh_pre_ctime = inode->i_ctime;
@@ -255,7 +255,7 @@ fill_pre_wcc(struct svc_fh *fhp)
static inline void
fill_post_wcc(struct svc_fh *fhp)
{
- struct inode *inode = fhp->fh_dentry->d_inode;
+ struct inode *inode = fhp->fh_path.dentry->d_inode;
if (fhp->fh_post_saved)
printk("nfsd: inode locked twice during operation.\n");
@@ -290,7 +290,7 @@ fill_post_wcc(struct svc_fh *fhp)
static inline void
fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
{
- struct dentry *dentry = fhp->fh_dentry;
+ struct dentry *dentry = fhp->fh_path.dentry;
struct inode *inode;
dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
@@ -322,11 +322,11 @@ fh_lock(struct svc_fh *fhp)
static inline void
fh_unlock(struct svc_fh *fhp)
{
- BUG_ON(!fhp->fh_dentry);
+ BUG_ON(!fhp->fh_path.dentry);
if (fhp->fh_locked) {
fill_post_wcc(fhp);
- mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
+ mutex_unlock(&fhp->fh_path.dentry->d_inode->i_mutex);
fhp->fh_locked = 0;
}
}
Index: linux-2.6/include/linux/nfsd/xdr4.h
===================================================================
--- linux-2.6.orig/include/linux/nfsd/xdr4.h
+++ linux-2.6/include/linux/nfsd/xdr4.h
@@ -433,7 +433,7 @@ int nfs4svc_encode_compoundres(struct sv
void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op);
__be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
- struct dentry *dentry, __be32 *buffer, int *countp,
+ struct path *path, __be32 *buffer, int *countp,
u32 *bmval, struct svc_rqst *);
extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
struct nfsd4_compound_state *,

View file

@ -1,91 +0,0 @@
Index: linux-2.6/include/linux/security.h
===================================================================
--- linux-2.6.orig/include/linux/security.h
+++ linux-2.6/include/linux/security.h
@@ -361,8 +361,7 @@ struct request_sock;
* Return 0 if permission is granted.
* @inode_getattr:
* Check permission before obtaining file attributes.
- * @mnt is the vfsmount where the dentry was looked up
- * @dentry contains the dentry structure for the file.
+ * @path contains the vfsmount and dentry of the file.
* Return 0 if permission is granted.
* @inode_delete:
* @inode contains the inode structure for deleted inode.
@@ -1221,7 +1220,7 @@ struct security_operations {
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
- int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
+ int (*inode_getattr) (struct path *path);
void (*inode_delete) (struct inode *inode);
int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
size_t size, int flags);
@@ -1713,12 +1712,11 @@ static inline int security_inode_setattr
return security_ops->inode_setattr (dentry, attr);
}
-static inline int security_inode_getattr (struct vfsmount *mnt,
- struct dentry *dentry)
+static inline int security_inode_getattr (struct path *path)
{
- if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ if (unlikely (IS_PRIVATE (path->dentry->d_inode)))
return 0;
- return security_ops->inode_getattr (mnt, dentry);
+ return security_ops->inode_getattr (path);
}
static inline void security_inode_delete (struct inode *inode)
@@ -2414,8 +2412,7 @@ static inline int security_inode_setattr
return 0;
}
-static inline int security_inode_getattr (struct vfsmount *mnt,
- struct dentry *dentry)
+static inline int security_inode_getattr (struct path *path)
{
return 0;
}
Index: linux-2.6/security/dummy.c
===================================================================
--- linux-2.6.orig/security/dummy.c
+++ linux-2.6/security/dummy.c
@@ -333,7 +333,7 @@ static int dummy_inode_setattr (struct d
return 0;
}
-static int dummy_inode_getattr (struct vfsmount *mnt, struct dentry *dentry)
+static int dummy_inode_getattr (struct path *path)
{
return 0;
}
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c
+++ linux-2.6/security/selinux/hooks.c
@@ -2243,9 +2243,9 @@ static int selinux_inode_setattr(struct
return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
}
-static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int selinux_inode_getattr(struct path *path)
{
- return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
+ return dentry_has_perm(current, path->mnt, path->dentry, FILE__GETATTR);
}
static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
Index: linux-2.6/fs/stat.c
===================================================================
--- linux-2.6.orig/fs/stat.c
+++ linux-2.6/fs/stat.c
@@ -43,7 +43,7 @@ int vfs_getattr(struct path *path, struc
struct inode *inode = path->dentry->d_inode;
int retval;
- retval = security_inode_getattr(path->mnt, path->dentry);
+ retval = security_inode_getattr(path);
if (retval)
return retval;

View file

@ -1,241 +0,0 @@
Index: linux-2.6/drivers/block/loop.c
===================================================================
--- linux-2.6.orig/drivers/block/loop.c
+++ linux-2.6/drivers/block/loop.c
@@ -1000,7 +1000,7 @@ loop_get_status(struct loop_device *lo,
if (lo->lo_state != Lo_bound)
return -ENXIO;
- error = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat);
+ error = vfs_getattr(&file->f_path, &stat);
if (error)
return error;
memset(info, 0, sizeof(*info));
Index: linux-2.6/fs/gfs2/ops_fstype.c
===================================================================
--- linux-2.6.orig/fs/gfs2/ops_fstype.c
+++ linux-2.6/fs/gfs2/ops_fstype.c
@@ -827,7 +827,7 @@ static struct super_block* get_gfs2_sb(c
dev_name);
goto out;
}
- error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat);
+ error = vfs_getattr(&nd.path, &stat);
fstype = get_fs_type("gfs2");
list_for_each(l, &fstype->fs_supers) {
Index: linux-2.6/fs/nfsd/nfs3proc.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs3proc.c
+++ linux-2.6/fs/nfsd/nfs3proc.c
@@ -58,6 +58,7 @@ nfsd3_proc_getattr(struct svc_rqst *rqst
{
int err;
__be32 nfserr;
+ struct path path;
dprintk("nfsd: GETATTR(3) %s\n",
SVCFH_fmt(&argp->fh));
@@ -67,8 +68,9 @@ nfsd3_proc_getattr(struct svc_rqst *rqst
if (nfserr)
RETURN_STATUS(nfserr);
- err = vfs_getattr(resp->fh.fh_export->ex_mnt,
- resp->fh.fh_dentry, &resp->stat);
+ path.mnt = resp->fh.fh_export->ex_mnt;
+ path.dentry = resp->fh.fh_dentry;
+ err = vfs_getattr(&path, &resp->stat);
nfserr = nfserrno(err);
RETURN_STATUS(nfserr);
Index: linux-2.6/fs/nfsd/nfs3xdr.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs3xdr.c
+++ linux-2.6/fs/nfsd/nfs3xdr.c
@@ -223,12 +223,15 @@ encode_saved_post_attr(struct svc_rqst *
static __be32 *
encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
{
- struct dentry *dentry = fhp->fh_dentry;
- if (dentry && dentry->d_inode != NULL) {
+ struct path path;
+
+ path.dentry = fhp->fh_dentry;
+ if (path.dentry && path.dentry->d_inode != NULL) {
int err;
struct kstat stat;
- err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat);
+ path.mnt = fhp->fh_export->ex_mnt;
+ err = vfs_getattr(&path, &stat);
if (!err) {
*p++ = xdr_one; /* attributes follow */
return encode_fattr3(rqstp, p, fhp, &stat);
Index: linux-2.6/fs/nfsd/nfs4xdr.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfs4xdr.c
+++ linux-2.6/fs/nfsd/nfs4xdr.c
@@ -1442,6 +1442,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
int err;
int aclsupport = 0;
struct nfs4_acl *acl = NULL;
+ struct path path;
BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
@@ -1453,7 +1454,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
goto out;
}
- err = vfs_getattr(exp->ex_mnt, dentry, &stat);
+ path.mnt = exp->ex_mnt;
+ path.dentry = dentry;
+ err = vfs_getattr(&path, &stat);
if (err)
goto out_nfserr;
if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
Index: linux-2.6/fs/nfsd/nfsproc.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfsproc.c
+++ linux-2.6/fs/nfsd/nfsproc.c
@@ -39,18 +39,25 @@ nfsd_proc_null(struct svc_rqst *rqstp, v
static __be32
nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp)
{
- if (err) return err;
- return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
- resp->fh.fh_dentry,
- &resp->stat));
+ struct path path;
+
+ if (err)
+ return err;
+ path.mnt = resp->fh.fh_export->ex_mnt;
+ path.dentry = resp->fh.fh_dentry;
+ return nfserrno(vfs_getattr(&path, &resp->stat));
}
+
static __be32
nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp)
{
- if (err) return err;
- return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
- resp->fh.fh_dentry,
- &resp->stat));
+ struct path path;
+
+ if (err)
+ return err;
+ path.mnt = resp->fh.fh_export->ex_mnt;
+ path.dentry = resp->fh.fh_dentry;
+ return nfserrno(vfs_getattr(&path, &resp->stat));
}
/*
* Get a file's attributes
@@ -136,6 +143,7 @@ static __be32
nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
struct nfsd_readres *resp)
{
+ struct path path;
__be32 nfserr;
dprintk("nfsd: READ %s %d bytes at %d\n",
@@ -162,10 +170,11 @@ nfsd_proc_read(struct svc_rqst *rqstp, s
rqstp->rq_vec, argp->vlen,
&resp->count);
- if (nfserr) return nfserr;
- return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
- resp->fh.fh_dentry,
- &resp->stat));
+ if (nfserr)
+ return nfserr;
+ path.mnt = resp->fh.fh_export->ex_mnt;
+ path.dentry = resp->fh.fh_dentry;
+ return nfserrno(vfs_getattr(&path, &resp->stat));
}
/*
Index: linux-2.6/fs/nfsd/nfsxdr.c
===================================================================
--- linux-2.6.orig/fs/nfsd/nfsxdr.c
+++ linux-2.6/fs/nfsd/nfsxdr.c
@@ -193,7 +193,11 @@ encode_fattr(struct svc_rqst *rqstp, __b
__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
{
struct kstat stat;
- vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, &stat);
+ struct path path;
+
+ path.mnt = fhp->fh_export->ex_mnt;
+ path.dentry = fhp->fh_dentry;
+ vfs_getattr(&path, &stat);
return encode_fattr(rqstp, p, fhp, &stat);
}
Index: linux-2.6/fs/stat.c
===================================================================
--- linux-2.6.orig/fs/stat.c
+++ linux-2.6/fs/stat.c
@@ -38,17 +38,17 @@ void generic_fillattr(struct inode *inod
EXPORT_SYMBOL(generic_fillattr);
-int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int vfs_getattr(struct path *path, struct kstat *stat)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = path->dentry->d_inode;
int retval;
- retval = security_inode_getattr(mnt, dentry);
+ retval = security_inode_getattr(path->mnt, path->dentry);
if (retval)
return retval;
if (inode->i_op->getattr)
- return inode->i_op->getattr(mnt, dentry, stat);
+ return inode->i_op->getattr(path->mnt, path->dentry, stat);
generic_fillattr(inode, stat);
return 0;
@@ -63,7 +63,7 @@ int vfs_stat_fd(int dfd, char __user *na
error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
if (!error) {
- error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat);
+ error = vfs_getattr(&nd.path, stat);
path_release(&nd);
}
return error;
@@ -83,7 +83,7 @@ int vfs_lstat_fd(int dfd, char __user *n
error = __user_walk_fd(dfd, name, 0, &nd);
if (!error) {
- error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat);
+ error = vfs_getattr(&nd.path, stat);
path_release(&nd);
}
return error;
@@ -102,7 +102,7 @@ int vfs_fstat(unsigned int fd, struct ks
int error = -EBADF;
if (f) {
- error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
+ error = vfs_getattr(&f->f_path, stat);
fput(f);
}
return error;
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1825,7 +1825,7 @@ extern int page_symlink(struct inode *in
extern struct inode_operations page_symlink_inode_operations;
extern int generic_readlink(struct dentry *, char __user *, int);
extern void generic_fillattr(struct inode *, struct kstat *);
-extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int vfs_getattr(struct path *, struct kstat *);
void inode_add_bytes(struct inode *inode, loff_t bytes);
void inode_sub_bytes(struct inode *inode, loff_t bytes);
loff_t inode_get_bytes(struct inode *inode);

View file

@ -8,44 +8,33 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/open.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
fs/open.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
--- a/fs/open.c
+++ b/fs/open.c
@@ -501,10 +501,8 @@ out:
@@ -512,8 +512,8 @@ out:
asmlinkage long sys_fchdir(unsigned int fd)
{
+ struct nameidata nd;
+ struct nameidata nd = { .flags = 0 };
struct file *file;
- struct dentry *dentry;
- struct inode *inode;
- struct vfsmount *mnt;
int error;
error = -EBADF;
@@ -512,17 +510,17 @@ asmlinkage long sys_fchdir(unsigned int
@@ -521,12 +521,11 @@ asmlinkage long sys_fchdir(unsigned int
if (!file)
goto out;
- dentry = file->f_path.dentry;
- mnt = file->f_path.mnt;
- inode = dentry->d_inode;
+ nd.dentry = file->f_path.dentry;
+ nd.mnt = file->f_path.mnt;
+ nd.flags = 0;
- inode = file->f_path.dentry->d_inode;
-
error = -ENOTDIR;
- if (!S_ISDIR(inode->i_mode))
+ if (!S_ISDIR(nd.dentry->d_inode->i_mode))
+ if (!S_ISDIR(file->f_path.dentry->d_inode->i_mode))
goto out_putf;
- error = file_permission(file, MAY_EXEC);
+ error = vfs_permission(&nd, MAY_EXEC);
+ nd.path = file->f_path;
error = file_permission(file, MAY_EXEC);
if (!error)
- set_fs_pwd(current->fs, mnt, dentry);
+ set_fs_pwd(current->fs, nd.mnt, nd.dentry);
out_putf:
fput(file);
out:
set_fs_pwd(current->fs, &file->f_path);

View file

@ -11,12 +11,12 @@ Reviewed-by: James Morris <jmorris@namei.org>
---
include/linux/sysctl.h | 2 ++
kernel/sysctl.c | 27 +++++++++++++++++++++++++++
security/selinux/hooks.c | 35 +++++------------------------------
3 files changed, 34 insertions(+), 30 deletions(-)
security/selinux/hooks.c | 34 +++++-----------------------------
3 files changed, 34 insertions(+), 29 deletions(-)
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -983,6 +983,8 @@ extern int proc_doulongvec_minmax(struct
@@ -980,6 +980,8 @@ extern int proc_doulongvec_minmax(struct
extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
struct file *, void __user *, size_t *, loff_t *);
@ -27,11 +27,11 @@ Reviewed-by: James Morris <jmorris@namei.org>
void __user *newval, size_t newlen);
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1327,6 +1327,33 @@ struct ctl_table_header *sysctl_head_nex
return NULL;
@@ -1435,6 +1435,33 @@ void register_sysctl_root(struct ctl_tab
spin_unlock(&sysctl_lock);
}
+char *sysctl_pathname(ctl_table *table, char *buffer, int buflen)
+char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
+{
+ if (buflen < 1)
+ return NULL;
@ -56,14 +56,14 @@ Reviewed-by: James Morris <jmorris@namei.org>
+
+ return buffer;
+}
+EXPORT_SYMBOL(sysctl_pathname);
+EXPORT_SYMBOL_GPL(sysctl_pathname);
+
#ifdef CONFIG_SYSCTL_SYSCALL
int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
/* Perform the actual read/write of a sysctl table entry. */
static int do_sysctl_strategy(struct ctl_table_root *root,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1431,40 +1431,15 @@ static int selinux_capable(struct task_s
@@ -1736,40 +1736,16 @@ static int selinux_capable(struct task_s
static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
{
@ -76,7 +76,7 @@ Reviewed-by: James Morris <jmorris@namei.org>
buffer = (char *)__get_free_page(GFP_KERNEL);
if (!buffer)
goto out;
-
- buflen = PAGE_SIZE;
- end = buffer+buflen;
- *--end = '\0';

View file

@ -25,216 +25,177 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
---
fs/dcache.c | 169 ++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 98 insertions(+), 71 deletions(-)
fs/dcache.c | 126 ++++++++++++++++++++++++++-----------------------
fs/seq_file.c | 4 -
include/linux/dcache.h | 5 +
3 files changed, 74 insertions(+), 61 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1764,52 +1764,51 @@ shouldnt_be_hashed:
}
/**
- * d_path - return the path of a dentry
+ * __d_path - return the path of a dentry
* @dentry: dentry to report
* @vfsmnt: vfsmnt to which the dentry belongs
* @root: root dentry
* @rootmnt: vfsmnt to which the root dentry belongs
@@ -1768,44 +1768,46 @@ static int prepend_name(char **buffer, i
* @root: root vfsmnt/dentry (may be modified by this function)
* @buffer: buffer to return value in
* @buflen: buffer length
+ * @fail_deleted: what to return for deleted files
+ * @flags: flags controling behavior of d_path
*
- * Convert a dentry into an ASCII path name. If the entry has been deleted
+ * Convert a dentry into an ASCII path name. If the entry has been deleted,
+ * then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
* the string " (deleted)" is appended. Note that this is ambiguous.
*
- * the string " (deleted)" is appended. Note that this is ambiguous.
- *
- * Returns the buffer or an error code if the path was too long.
+ * If @dentry is not connected to @root, the path returned will be relative
+ * (i.e., it will not start with a slash).
*
- *
- * "buflen" should be positive. Caller holds the dcache_lock.
+ * Returns the buffer or an error code.
+ * Convert a dentry into an ASCII path name. If the entry has been deleted,
+ * then if @flags has D_PATH_FAIL_DELETED set, ERR_PTR(-ENOENT) is returned.
+ * Otherwise, the string " (deleted)" is appended. Note that this is ambiguous.
*
* If path is not reachable from the supplied root, then the value of
- * root is changed (without modifying refcounts).
+ * root is changed (without modifying refcounts). The path returned in this
+ * case will be relative (i.e., it will not start with a slash).
+ *
+ * Returns the buffer or an error code if the path was too long.
*/
-static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
- struct dentry *root, struct vfsmount *rootmnt,
char *__d_path(const struct path *path, struct path *root,
- char *buffer, int buflen)
-{
+ char *buffer, int buflen, int flags)
{
struct dentry *dentry = path->dentry;
struct vfsmount *vfsmnt = path->mnt;
- char *end = buffer + buflen;
- char *retval;
- int namelen;
+static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ struct dentry *root, struct vfsmount *rootmnt,
+ char *buffer, int buflen, int fail_deleted)
+{
+ int namelen, is_slash;
+ const unsigned char *name;
+ int namelen;
+
+ if (buflen < 2)
+ return ERR_PTR(-ENAMETOOLONG);
+ buffer += --buflen;
+ *buffer = '\0';
+ buffer += buflen;
+ prepend(&buffer, &buflen, "\0", 1);
- *--end = '\0';
- buflen--;
spin_lock(&vfsmount_lock);
- prepend(&end, &buflen, "\0", 1);
- if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
- (prepend(&end, &buflen, " (deleted)", 10) != 0))
+ spin_lock(&dcache_lock);
if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
- buflen -= 10;
- end -= 10;
- if (buflen < 0)
+ if (fail_deleted) {
+ if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
+ if (flags & D_PATH_FAIL_DELETED) {
+ buffer = ERR_PTR(-ENOENT);
+ goto out;
+ }
+ if (buflen < 10)
+ if (prepend(&buffer, &buflen, " (deleted)", 10) != 0)
goto Elong;
- memcpy(end, " (deleted)", 10);
+ buflen -= 10;
+ buffer -= 10;
+ memcpy(buffer, " (deleted)", 10);
}
-
- if (buflen < 1)
- goto Elong;
+ }
if (buflen < 1)
goto Elong;
- /* Get '/' right */
- retval = end-1;
- *retval = '/';
-
- for (;;) {
+ while (dentry != root || vfsmnt != rootmnt) {
+ while (dentry != root->dentry || vfsmnt != root->mnt) {
struct dentry * parent;
- if (dentry == root && vfsmnt == rootmnt)
- if (dentry == root->dentry && vfsmnt == root->mnt)
- break;
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
- /* Global root? */
spin_lock(&vfsmount_lock);
if (vfsmnt->mnt_parent == vfsmnt) {
spin_unlock(&vfsmount_lock);
@@ -1823,33 +1822,72 @@ static char * __d_path( struct dentry *d
goto global_root;
}
@@ -1815,27 +1817,51 @@ char *__d_path(const struct path *path,
}
parent = dentry->d_parent;
prefetch(parent);
namelen = dentry->d_name.len;
- buflen -= namelen + 1;
- if (buflen < 0)
+ if (buflen < namelen + 1)
- if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
- (prepend(&end, &buflen, "/", 1) != 0))
+ if ((prepend_name(&buffer, &buflen, &dentry->d_name) != 0) ||
+ (prepend(&buffer, &buflen, "/", 1) != 0))
goto Elong;
- end -= namelen;
- memcpy(end, dentry->d_name.name, namelen);
- *--end = '/';
- retval = end;
+ buflen -= namelen + 1;
+ buffer -= namelen;
+ memcpy(buffer, dentry->d_name.name, namelen);
+ *--buffer = '/';
dentry = parent;
}
+ /* Get '/' right. */
+ if (*buffer != '/')
+ *--buffer = '/';
+ if (*buffer != '/' && prepend(&buffer, &buflen, "/", 1))
+ goto Elong;
- return retval;
+out:
out:
+ spin_unlock(&dcache_lock);
spin_unlock(&vfsmount_lock);
- return retval;
+ return buffer;
global_root:
- retval += 1; /* hit the slash */
- if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
+ /*
+ * We went past the (vfsmount, dentry) we were looking for and have
+ * either hit a root dentry, a lazily unmounted dentry, an
+ * unconnected dentry, or the file is on a pseudo filesystem.
+ */
namelen = dentry->d_name.len;
- buflen -= namelen;
- if (buflen < 0)
+ is_slash = (namelen == 1 && *dentry->d_name.name == '/');
+ if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
+ namelen = dentry->d_name.len;
+ name = dentry->d_name.name;
+
+ /*
+ * Make sure we won't return a pathname starting with '/'.
+ *
+ * Historically, we also glue together the root dentry and
+ * remaining name for pseudo filesystems like pipefs, which
+ * have the MS_NOUSER flag set. This results in pathnames
+ * like "pipe:[439336]".
+ * If this is a root dentry, then overwrite the slash. This
+ * will also DTRT with pseudo filesystems which have root
+ * dentries named "foo:".
+ */
+ if (*buffer == '/') {
+ if (IS_ROOT(dentry) && *buffer == '/') {
+ buffer++;
+ buflen++;
+ }
+ if (is_slash)
+ goto out;
+ if ((flags & D_PATH_DISCONNECT) && *name == '/') {
+ /* Make sure we won't return a pathname starting with '/' */
+ name++;
+ namelen--;
+ }
+ if (buflen < namelen)
+ if (prepend(&buffer, &buflen, name, namelen))
goto Elong;
- retval -= namelen-1; /* hit the slash */
- memcpy(retval, dentry->d_name.name, namelen);
- return retval;
+ buffer -= namelen;
+ memcpy(buffer, dentry->d_name.name, namelen);
+ goto out;
+
root->mnt = vfsmnt;
root->dentry = dentry;
goto out;
Elong:
- return ERR_PTR(-ENAMETOOLONG);
- retval = ERR_PTR(-ENAMETOOLONG);
+ buffer = ERR_PTR(-ENAMETOOLONG);
+ goto out;
+}
+
+static char *__connect_d_path(char *path, char *buffer)
+{
+ if (!IS_ERR(path) && *path != '/') {
+ /* Pretend that disconnected paths are hanging off the root. */
+ if (path == buffer)
+ path = ERR_PTR(-ENAMETOOLONG);
+ else
+ *--path = '/';
+ }
+ return path;
goto out;
}
/* write full pathname into buffer and return start of pathname */
-char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
- char *buf, int buflen)
+char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
+ int buflen)
{
char *res;
struct vfsmount *rootmnt;
@@ -1869,9 +1907,8 @@ char * d_path(struct dentry *dentry, str
rootmnt = mntget(current->fs->rootmnt);
root = dget(current->fs->root);
@@ -1872,10 +1898,8 @@ char *d_path(const struct path *path, ch
root = current->fs->root;
path_get(&root);
read_unlock(&current->fs->lock);
- spin_lock(&dcache_lock);
- res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
tmp = root;
- res = __d_path(path, &tmp, buf, buflen);
- spin_unlock(&dcache_lock);
+ res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
+ res = __connect_d_path(res, buf);
dput(root);
mntput(rootmnt);
+ res = __d_path(path, &tmp, buf, buflen, 0);
path_put(&root);
return res;
@@ -1918,10 +1955,10 @@ char *dynamic_dname(struct dentry *dentr
}
@@ -1958,9 +1982,9 @@ Elong:
*/
asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
{
- int error;
+ int error, len;
struct vfsmount *pwdmnt, *rootmnt;
struct dentry *pwd, *root;
struct path pwd, root;
- char *page = (char *) __get_free_page(GFP_USER);
+ char *page = (char *) __get_free_page(GFP_USER), *cwd;
if (!page)
return -ENOMEM;
@@ -1933,29 +1970,19 @@ asmlinkage long sys_getcwd(char __user *
root = dget(current->fs->root);
@@ -1972,30 +1996,18 @@ asmlinkage long sys_getcwd(char __user *
path_get(&root);
read_unlock(&current->fs->lock);
- error = -ENOENT;
- /* Has the current directory has been unlinked? */
- spin_lock(&dcache_lock);
- if (pwd->d_parent == pwd || !d_unhashed(pwd)) {
- if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) {
- unsigned long len;
- struct path tmp = root;
- char * cwd;
-
- cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
- cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
- spin_unlock(&dcache_lock);
-
- error = PTR_ERR(cwd);
@ -250,8 +211,7 @@ Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
- }
- } else
- spin_unlock(&dcache_lock);
+ cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
+ cwd = __connect_d_path(cwd, page);
+ cwd = __d_path(&pwd, &root, page, PAGE_SIZE, 0);
+ error = PTR_ERR(cwd);
+ if (IS_ERR(cwd))
+ goto out;
@ -265,4 +225,33 @@ Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
+ }
out:
dput(pwd);
path_put(&pwd);
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -405,9 +405,7 @@ int seq_path_root(struct seq_file *m, st
char *s = m->buf + m->count;
char *p;
- spin_lock(&dcache_lock);
- p = __d_path(path, root, s, m->size - m->count);
- spin_unlock(&dcache_lock);
+ p = __d_path(path, root, s, m->size - m->count, 0);
err = PTR_ERR(p);
if (!IS_ERR(p)) {
s = mangle_path(s, p, esc);
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -297,9 +297,12 @@ extern int d_validate(struct dentry *, s
/*
* helper function for dentry_operations.d_dname() members
*/
+#define D_PATH_FAIL_DELETED 1
+#define D_PATH_DISCONNECT 2
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
-extern char *__d_path(const struct path *path, struct path *root, char *, int);
+extern char *__d_path(const struct path *path, struct path *root, char *, int,
+ int);
extern char *d_path(const struct path *, char *, int);
extern char *dentry_path(struct dentry *, char *, int);

Some files were not shown because too many files have changed in this diff Show more