diff options
author | Jiri Kosina <jkosina@suse.cz> | 2010-06-16 18:08:13 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2010-06-16 18:08:13 +0200 |
commit | f1bbbb6912662b9f6070c5bfc4ca9eb1f06a9d5b (patch) | |
tree | c2c130a74be25b0b2dff992e1a195e2728bdaadd /security | |
parent | fd0961ff67727482bb20ca7e8ea97b83e9de2ddb (diff) | |
parent | 7e27d6e778cd87b6f2415515d7127eba53fe5d02 (diff) | |
download | linux-f1bbbb6912662b9f6070c5bfc4ca9eb1f06a9d5b.tar.gz linux-f1bbbb6912662b9f6070c5bfc4ca9eb1f06a9d5b.tar.bz2 linux-f1bbbb6912662b9f6070c5bfc4ca9eb1f06a9d5b.zip |
Merge branch 'master' into for-next
Diffstat (limited to 'security')
-rw-r--r-- | security/keys/internal.h | 1 | ||||
-rw-r--r-- | security/keys/keyctl.c | 2 | ||||
-rw-r--r-- | security/keys/keyring.c | 6 | ||||
-rw-r--r-- | security/keys/process_keys.c | 3 | ||||
-rw-r--r-- | security/keys/request_key.c | 32 | ||||
-rw-r--r-- | security/selinux/hooks.c | 55 | ||||
-rw-r--r-- | security/selinux/include/objsec.h | 1 |
7 files changed, 46 insertions, 54 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h index 5d4402a1161a..38783dcf6c61 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -124,6 +124,7 @@ extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); extern int install_user_keyrings(void); extern int install_thread_keyring_to_cred(struct cred *); extern int install_process_keyring_to_cred(struct cred *); +extern int install_session_keyring_to_cred(struct cred *, struct key *); extern struct key *request_key_and_link(struct key_type *type, const char *description, diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 8f4dce1987c4..13074b454743 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1269,7 +1269,7 @@ long keyctl_session_to_parent(void) goto not_permitted; /* the parent must be single threaded */ - if (atomic_read(&parent->signal->count) != 1) + if (!thread_group_empty(parent)) goto not_permitted; /* the parent and the child must have different session keyrings or diff --git a/security/keys/keyring.c b/security/keys/keyring.c index ef03a82a0135..d37f713e73ce 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -669,7 +669,7 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) struct keyring_list *klist = container_of(rcu, struct keyring_list, rcu); - if (klist->delkey != USHORT_MAX) + if (klist->delkey != USHRT_MAX) key_put(klist->keys[klist->delkey]); kfree(klist); } @@ -746,7 +746,7 @@ int __key_link_begin(struct key *keyring, const struct key_type *type, max += klist->maxkeys; ret = -ENFILE; - if (max > USHORT_MAX - 1) + if (max > USHRT_MAX - 1) goto error_quota; size = sizeof(*klist) + sizeof(struct key *) * max; if (size > PAGE_SIZE) @@ -763,7 +763,7 @@ int __key_link_begin(struct key *keyring, const struct key_type *type, sizeof(struct key *) * klist->nkeys); nklist->delkey = klist->nkeys; nklist->nkeys = klist->nkeys + 1; - klist->delkey = USHORT_MAX; + klist->delkey = USHRT_MAX; } else { nklist->nkeys = 1; nklist->delkey = 0; diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 20a38fed61b1..6b8e4ff4cc68 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -216,8 +216,7 @@ static int install_process_keyring(void) /* * install a session keyring directly to a credentials struct */ -static int install_session_keyring_to_cred(struct cred *cred, - struct key *keyring) +int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) { unsigned long flags; struct key *old; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index f656e9c069e3..f5ec9ac5d57c 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -58,6 +58,38 @@ void complete_request_key(struct key_construction *cons, int error) } EXPORT_SYMBOL(complete_request_key); +static int umh_keys_init(struct subprocess_info *info) +{ + struct cred *cred = (struct cred*)current_cred(); + struct key *keyring = info->data; + /* + * This is called in context of freshly forked kthread before + * kernel_execve(), we can just change our ->session_keyring. + */ + return install_session_keyring_to_cred(cred, keyring); +} + +static void umh_keys_cleanup(struct subprocess_info *info) +{ + struct key *keyring = info->data; + key_put(keyring); +} + +static int call_usermodehelper_keys(char *path, char **argv, char **envp, + struct key *session_keyring, enum umh_wait wait) +{ + gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; + struct subprocess_info *info = + call_usermodehelper_setup(path, argv, envp, gfp_mask); + + if (!info) + return -ENOMEM; + + call_usermodehelper_setfns(info, umh_keys_init, umh_keys_cleanup, + key_get(session_keyring)); + return call_usermodehelper_exec(info, wait); +} + /* * request userspace finish the construction of a key * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a03fd74602b4..5c9f25ba1c95 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -126,11 +126,6 @@ __setup("selinux=", selinux_enabled_setup); int selinux_enabled = 1; #endif -/* Lists of inode and superblock security structures initialized - before the policy was loaded. */ -static LIST_HEAD(superblock_security_head); -static DEFINE_SPINLOCK(sb_security_lock); - static struct kmem_cache *sel_inode_cache; /** @@ -266,7 +261,6 @@ static int superblock_alloc_security(struct super_block *sb) return -ENOMEM; mutex_init(&sbsec->lock); - INIT_LIST_HEAD(&sbsec->list); INIT_LIST_HEAD(&sbsec->isec_head); spin_lock_init(&sbsec->isec_lock); sbsec->sb = sb; @@ -281,12 +275,6 @@ static int superblock_alloc_security(struct super_block *sb) static void superblock_free_security(struct super_block *sb) { struct superblock_security_struct *sbsec = sb->s_security; - - spin_lock(&sb_security_lock); - if (!list_empty(&sbsec->list)) - list_del_init(&sbsec->list); - spin_unlock(&sb_security_lock); - sb->s_security = NULL; kfree(sbsec); } @@ -612,10 +600,6 @@ static int selinux_set_mnt_opts(struct super_block *sb, /* Defer initialization until selinux_complete_init, after the initial policy is loaded and the security server is ready to handle calls. */ - spin_lock(&sb_security_lock); - if (list_empty(&sbsec->list)) - list_add(&sbsec->list, &superblock_security_head); - spin_unlock(&sb_security_lock); goto out; } rc = -EINVAL; @@ -806,16 +790,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, /* * if the parent was able to be mounted it clearly had no special lsm - * mount options. thus we can safely put this sb on the list and deal - * with it later + * mount options. thus we can safely deal with this superblock later */ - if (!ss_initialized) { - spin_lock(&sb_security_lock); - if (list_empty(&newsbsec->list)) - list_add(&newsbsec->list, &superblock_security_head); - spin_unlock(&sb_security_lock); + if (!ss_initialized) return; - } /* how can we clone if the old one wasn't set up?? */ BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); @@ -5680,35 +5658,18 @@ static __init int selinux_init(void) return 0; } +static void delayed_superblock_init(struct super_block *sb, void *unused) +{ + superblock_doinit(sb, NULL); +} + void selinux_complete_init(void) { printk(KERN_DEBUG "SELinux: Completing initialization.\n"); /* Set up any superblocks initialized prior to the policy load. */ printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); - spin_lock(&sb_lock); - spin_lock(&sb_security_lock); -next_sb: - if (!list_empty(&superblock_security_head)) { - struct superblock_security_struct *sbsec = - list_entry(superblock_security_head.next, - struct superblock_security_struct, - list); - struct super_block *sb = sbsec->sb; - sb->s_count++; - spin_unlock(&sb_security_lock); - spin_unlock(&sb_lock); - down_read(&sb->s_umount); - if (sb->s_root) - superblock_doinit(sb, NULL); - drop_super(sb); - spin_lock(&sb_lock); - spin_lock(&sb_security_lock); - list_del_init(&sbsec->list); - goto next_sb; - } - spin_unlock(&sb_security_lock); - spin_unlock(&sb_lock); + iterate_supers(delayed_superblock_init, NULL); } /* SELinux requires early initialization in order to label diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index c4e062336ef3..26c7eee1c309 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -55,7 +55,6 @@ struct file_security_struct { struct superblock_security_struct { struct super_block *sb; /* back pointer to sb object */ - struct list_head list; /* list of superblock_security_struct */ u32 sid; /* SID of file system superblock */ u32 def_sid; /* default SID for labeling */ u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ |