fixes to issues that came up in updating the regression tests

This commit is contained in:
John Johansen 2007-03-13 21:44:05 +00:00
parent 063bb1b26e
commit e102bd2651
7 changed files with 338 additions and 16 deletions

View file

@ -0,0 +1,166 @@
Index: b/security/apparmor/apparmor.h
===================================================================
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -141,7 +141,7 @@ extern rwlock_t profile_list_lock;
*/
struct aa_task_context {
struct aa_profile *profile; /* The current profile */
- u32 hat_magic; /* used with change_hat */
+ u64 hat_magic; /* used with change_hat */
struct list_head list;
struct task_struct *task;
kernel_cap_t caps_logged;
@@ -235,7 +235,7 @@ extern int aa_link(struct aa_profile *pr
extern int aa_clone(struct task_struct *task);
extern int aa_register(struct linux_binprm *bprm);
extern void aa_release(struct task_struct *task);
-extern int aa_change_hat(const char *id, u32 hat_magic);
+extern int aa_change_hat(const char *id, u64 hat_magic);
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,
Index: b/security/apparmor/inline.h
===================================================================
--- a/security/apparmor/inline.h
+++ b/security/apparmor/inline.h
@@ -69,7 +69,7 @@ static inline struct aa_profile *aa_find
*/
static inline void aa_change_profile(struct aa_task_context *cxt,
struct aa_profile *profile,
- u32 hat_magic)
+ u64 hat_magic)
{
struct aa_profile *old_profile = cxt->profile;
Index: b/security/apparmor/main.c
===================================================================
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -1035,7 +1035,7 @@ repeat:
*/
static inline int do_change_hat(const char *hat_name,
struct aa_task_context *cxt,
- u32 hat_magic)
+ u64 hat_magic)
{
struct aa_profile *sub;
int error = 0;
@@ -1110,7 +1110,7 @@ static inline int do_change_hat(const ch
* return to original top level profile. Returns %0 on success, error
* otherwise.
*/
-int aa_change_hat(const char *hat_name, u32 hat_magic)
+int aa_change_hat(const char *hat_name, u64 hat_magic)
{
struct aa_task_context *cxt;
struct aa_profile *profile;
@@ -1118,7 +1118,7 @@ int aa_change_hat(const char *hat_name,
/* Dump out above debugging in WARN mode if we are in AUDIT mode */
if (APPARMOR_AUDIT(aa_task_context(current))) {
- AA_WARN("%s: %s, 0x%x (pid %d)\n",
+ AA_WARN("%s: %s, 0x%llx (pid %d)\n",
__FUNCTION__, hat_name ? hat_name : "NULL",
hat_magic, current->pid);
}
@@ -1148,7 +1148,7 @@ repeat:
if (profile == profile->parent) {
/* We are in the parent profile. */
if (hat_name) {
- AA_DEBUG("%s: switching to %s, 0x%x\n",
+ AA_DEBUG("%s: switching to %s, 0x%llx\n",
__FUNCTION__,
hat_name,
hat_magic);
@@ -1188,7 +1188,7 @@ repeat:
}
} else if (cxt->hat_magic) {
AA_ERROR("KILLING process %s(%d) "
- "Invalid change_hat() magic# 0x%x "
+ "Invalid change_hat() magic# 0x%llx "
"(hatname %s profile %s active %s)\n",
current->comm, current->pid,
hat_magic,
Index: b/security/apparmor/procattr.c
===================================================================
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -79,9 +79,8 @@ size_t aa_getprocattr(struct aa_profile
int aa_setprocattr_changehat(char *hatinfo, size_t infosize)
{
int error = -EINVAL;
- char *token = NULL, *hat, *smagic, *tmp;
- u32 magic;
- int rc, len, consumed;
+ char *token = NULL, *hat;
+ u64 magic;
AA_DEBUG("%s: %p %zd\n", __FUNCTION__, hatinfo, infosize);
@@ -92,7 +91,7 @@ int aa_setprocattr_changehat(char *hatin
}
if (infosize == 0)
- goto out;
+ return -EINVAL;
/*
* Copy string to a new buffer so we can play with it
@@ -100,50 +99,19 @@ int aa_setprocattr_changehat(char *hatin
* for 100% safety
*/
token = kmalloc(infosize + 1, GFP_KERNEL);
-
- if (!token) {
- error = -ENOMEM;
- goto out;
- }
-
+ if (!token)
+ return -ENOMEM;
memcpy(token, hatinfo, infosize);
token[infosize] = 0;
- /* error is INVAL until we have at least parsed something */
- error = -EINVAL;
-
- tmp = token;
- while (*tmp && *tmp != '^') {
- tmp++;
- }
-
- if (!*tmp || tmp == token) {
+ magic = simple_strtoull(token, &hat, 16);
+ if (hat == token || *hat != '^') {
AA_WARN("%s: Invalid input '%s'\n", __FUNCTION__, token);
goto out;
}
- /* split magic and hat into two strings */
- *tmp = 0;
- smagic = token;
-
- /*
- * Initially set consumed=strlen(magic), as if sscanf
- * consumes all input via the %x it will not process the %n
- * directive. Otherwise, if sscanf does not consume all the
- * input it will process the %n and update consumed.
- */
- consumed = len = strlen(smagic);
-
- rc = sscanf(smagic, "%x%n", &magic, &consumed);
-
- if (rc != 1 || consumed != len) {
- AA_WARN("%s: Invalid hex magic %s\n",
- __FUNCTION__,
- smagic);
- goto out;
- }
-
- hat = tmp + 1;
+ /* skip ^ */
+ hat++;
if (!*hat)
hat = NULL;

View file

@ -2,21 +2,12 @@ Index: b/security/apparmor/lsm.c
===================================================================
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -150,7 +150,7 @@ static int apparmor_sysctl(struct ctl_ta
int error = 0;
if ((op & 002) && !capable(CAP_SYS_ADMIN))
- error = aa_reject_syscall(current, GFP_KERNEL,
+ error = aa_reject_syscall(current, GFP_ATOMIC,
"sysctl (write)");
return error;
@@ -202,7 +202,7 @@ static int apparmor_bprm_secureexec(stru
static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
unsigned long flags, void *data)
{
- return aa_reject_syscall(current, GFP_KERNEL, "mount");
+ return aa_reject_syscall(current, GFP_ATOMIC, "mount");
}
@@ -207,7 +207,7 @@ static int apparmor_sb_mount(char *dev_n
static int apparmor_umount(struct vfsmount *mnt, int flags)
{
- return aa_reject_syscall(current, GFP_ATOMIC, "umount");
+ return aa_reject_syscall(current, GFP_KERNEL, "umount");
}
static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,

View file

@ -0,0 +1,14 @@
Index: b/security/apparmor/main.c
===================================================================
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -649,7 +649,8 @@ int aa_perm_dir(struct aa_profile *profi
sa.flags = 0;
sa.gfp_mask = GFP_KERNEL;
- return aa_perm_dentry(profile, dentry, mnt, &sa, mask, AA_CHECK_DIR);
+ return aa_perm_dentry(profile, dentry, mnt, &sa, mask,
+ AA_CHECK_DIR | AA_CHECK_LEAF);
}
/**

View file

@ -0,0 +1,90 @@
Index: b/security/apparmor/main.c
===================================================================
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -1048,6 +1048,14 @@ static inline int do_change_hat(const ch
if (sub) {
/* change hat */
aa_change_profile(cxt, sub, hat_magic);
+ /*
+ * aa_change_profile switches profile lists but we don't
+ * want this for change_hat. Switch back to the parents
+ * list.
+ * FIXME: update to a full profile change mechanism
+ * to get rid of this special casing
+ */
+ list_move(&cxt->list, &sub->parent->task_contexts);
} else {
struct aa_profile *profile = cxt->profile;
@@ -1078,6 +1086,14 @@ static inline int do_change_hat(const ch
* In learning mode, this allows us to learn about new hats.
*/
aa_change_profile(cxt, cxt->profile->null_profile, hat_magic);
+ /*
+ * aa_change_profile switches profile lists but we don't
+ * want this for change_hat. Switch back to the parents
+ * list.
+ * FIXME: update to a full profile change mechanism
+ * to get rid of this special casing
+ */
+ list_move(&cxt->list, &cxt->profile->parent->task_contexts);
}
return error;
@@ -1157,6 +1173,11 @@ repeat:
if (!hat_name) {
/* Return from subprofile back to parent. */
aa_change_profile(cxt, cxt->profile->parent, 0);
+ /*
+ * switching lists is not needed here because
+ * aa_change_profile list move will leave the
+ * cxt on the correct list
+ */
} else {
/*
* Change to another (sibling) profile, and
Index: b/security/apparmor/module_interface.c
===================================================================
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -57,6 +57,14 @@ static inline void task_replace(struct a
hat = aa_dup_profile(new_profile->null_profile);
aa_change_profile(cxt, hat, cxt->hat_magic);
+ /*
+ * aa_change_profile switches profile lists but we don't
+ * want this for change_hat. Switch back to the parents
+ * list.
+ * FIXME: update to a full profile change mechanism
+ * to get rid of this special casing
+ */
+ list_move(&cxt->list, &hat->parent->task_contexts);
aa_put_profile(hat);
} else
aa_change_profile(cxt, new_profile, cxt->hat_magic);
@@ -451,7 +459,14 @@ ssize_t aa_file_prof_replace(void *udata
write_lock(&profile_list_lock);
old_profile = __aa_find_profile(new_profile->name, &profile_list);
if (old_profile) {
- lock_profile(old_profile);
+ /*
+ * new_profile needs to be locked in the case that there
+ * are multiple tasks on old_profiles list, this avoids
+ * a race between an already replaced task changing its
+ * profile (updating the list) and replacement updating
+ * the list
+ */
+ lock_both_profiles(old_profile, new_profile);
old_profile->isstale = 1;
while (!list_empty(&old_profile->task_contexts)) {
struct aa_task_context *cxt =
@@ -461,7 +476,7 @@ ssize_t aa_file_prof_replace(void *udata
task_replace(cxt, new_profile);
task_unlock(cxt->task);
}
- unlock_profile(old_profile);
+ unlock_both_profiles(old_profile, new_profile);
list_del_init(&old_profile->list);
aa_put_profile(old_profile);

View file

@ -0,0 +1,31 @@
Index: b/fs/namei.c
===================================================================
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2016,6 +2016,10 @@ int vfs_rmdir(struct inode *dir, struct
if (!dir->i_op || !dir->i_op->rmdir)
return -EPERM;
+ error = security_inode_rmdir(dir, dentry, mnt);
+ if (error)
+ return error;
+
DQUOT_INIT(dir);
mutex_lock(&dentry->d_inode->i_mutex);
@@ -2023,12 +2027,9 @@ int vfs_rmdir(struct inode *dir, struct
if (d_mountpoint(dentry))
error = -EBUSY;
else {
- error = security_inode_rmdir(dir, dentry, mnt);
- if (!error) {
- error = dir->i_op->rmdir(dir, dentry);
- if (!error)
- dentry->d_inode->i_flags |= S_DEAD;
- }
+ error = dir->i_op->rmdir(dir, dentry);
+ if (!error)
+ dentry->d_inode->i_flags |= S_DEAD;
}
mutex_unlock(&dentry->d_inode->i_mutex);
if (!error) {

View file

@ -0,0 +1,25 @@
Index: b/security/apparmor/lsm.c
===================================================================
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -333,9 +333,18 @@ static int apparmor_inode_rename(struct
error = aa_perm(profile, old_dentry, old_mnt,
MAY_READ | MAY_WRITE, AA_CHECK_LEAF);
- if (!error && new_mnt)
+ if (!error && new_mnt) {
+ int check = 0;
+ /*
+ * if the new_dentry doesn't exist force it to be the
+ * same file/dir type as old_dentry
+ */
+ if (!new_dentry->d_inode && old_dentry->d_inode &&
+ S_ISDIR(old_dentry->d_inode->i_mode))
+ check = AA_CHECK_DIR;
error = aa_perm(profile, new_dentry, new_mnt,
- MAY_WRITE, AA_CHECK_LEAF);
+ MAY_WRITE, check | AA_CHECK_LEAF);
+ }
}
aa_put_profile(profile);

View file

@ -102,3 +102,8 @@ file-handle-ops.diff
file-handle-ops-2.diff
# unlink.diff
coding-style.diff
dir-leaf-nodes.diff
force_dir_on_negative_dentry.diff
fix-vfs_rmdir.diff
fix-change_hat-replacement.diff
64bit-changehat.diff