Merge branch 'master'; commit 'v2.6.39-rc3' into next
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 16ee8b4..04fed72 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -412,7 +412,6 @@
 
 # define CAP_EMPTY_SET    ((kernel_cap_t){{ 0, 0 }})
 # define CAP_FULL_SET     ((kernel_cap_t){{ ~0, ~0 }})
-# define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }})
 # define CAP_FS_SET       ((kernel_cap_t){{ CAP_FS_MASK_B0 \
 				    | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \
 				    CAP_FS_MASK_B1 } })
@@ -422,11 +421,7 @@
 
 #endif /* _KERNEL_CAPABILITY_U32S != 2 */
 
-#define CAP_INIT_INH_SET    CAP_EMPTY_SET
-
 # define cap_clear(c)         do { (c) = __cap_empty_set; } while (0)
-# define cap_set_full(c)      do { (c) = __cap_full_set; } while (0)
-# define cap_set_init_eff(c)  do { (c) = __cap_init_eff_set; } while (0)
 
 #define cap_raise(c, flag)  ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag))
 #define cap_lower(c, flag)  ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag))
@@ -547,6 +542,8 @@
 extern bool ns_capable(struct user_namespace *ns, int cap);
 extern bool task_ns_capable(struct task_struct *t, int cap);
 
+extern const kernel_cap_t __cap_empty_set;
+
 /**
  * nsown_capable - Check superior capability to one's own user_ns
  * @cap: The capability in question
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index caa151f..1f27720 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -83,13 +83,6 @@
 #define INIT_IDS
 #endif
 
-/*
- * Because of the reduced scope of CAP_SETPCAP when filesystem
- * capabilities are in effect, it is safe to allow CAP_SETPCAP to
- * be available in the default configuration.
- */
-# define CAP_INIT_BSET  CAP_FULL_SET
-
 #ifdef CONFIG_RCU_BOOST
 #define INIT_TASK_RCU_BOOST()						\
 	.rcu_boost_mutex = NULL,
diff --git a/include/linux/key.h b/include/linux/key.h
index b2bb017..ef19b99 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -276,6 +276,19 @@
 	return key ? key->serial : 0;
 }
 
+/**
+ * key_is_instantiated - Determine if a key has been positively instantiated
+ * @key: The key to check.
+ *
+ * Return true if the specified key has been positively instantiated, false
+ * otherwise.
+ */
+static inline bool key_is_instantiated(const struct key *key)
+{
+	return test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
+		!test_bit(KEY_FLAG_NEGATIVE, &key->flags);
+}
+
 #define rcu_dereference_key(KEY)					\
 	(rcu_dereference_protected((KEY)->payload.rcudata,		\
 				   rwsem_is_locked(&((struct key *)(KEY))->sem)))
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 6efd7a7..79bb98d 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -24,6 +24,7 @@
 #include <linux/errno.h>
 #include <linux/compiler.h>
 #include <linux/workqueue.h>
+#include <linux/sysctl.h>
 
 #define KMOD_PATH_LEN 256
 
@@ -109,6 +110,8 @@
 				       NULL, NULL, NULL);
 }
 
+extern struct ctl_table usermodehelper_table[];
+
 extern void usermodehelper_init(void);
 
 extern int usermodehelper_disable(void);
diff --git a/kernel/capability.c b/kernel/capability.c
index bf0c734..14ea4210 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -22,12 +22,8 @@
  */
 
 const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
-const kernel_cap_t __cap_full_set = CAP_FULL_SET;
-const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;
 
 EXPORT_SYMBOL(__cap_empty_set);
-EXPORT_SYMBOL(__cap_full_set);
-EXPORT_SYMBOL(__cap_init_eff_set);
 
 int file_caps_enabled = 1;
 
diff --git a/kernel/cred.c b/kernel/cred.c
index 5557b55..b982f08 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -49,10 +49,10 @@
 	.magic			= CRED_MAGIC,
 #endif
 	.securebits		= SECUREBITS_DEFAULT,
-	.cap_inheritable	= CAP_INIT_INH_SET,
+	.cap_inheritable	= CAP_EMPTY_SET,
 	.cap_permitted		= CAP_FULL_SET,
-	.cap_effective		= CAP_INIT_EFF_SET,
-	.cap_bset		= CAP_INIT_BSET,
+	.cap_effective		= CAP_FULL_SET,
+	.cap_bset		= CAP_FULL_SET,
 	.user			= INIT_USER,
 	.group_info		= &init_groups,
 #ifdef CONFIG_KEYS
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 9cd0591..06fdea2 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -25,6 +25,7 @@
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/completion.h>
+#include <linux/cred.h>
 #include <linux/file.h>
 #include <linux/fdtable.h>
 #include <linux/workqueue.h>
@@ -43,6 +44,13 @@
 
 static struct workqueue_struct *khelper_wq;
 
+#define CAP_BSET	(void *)1
+#define CAP_PI		(void *)2
+
+static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
+static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
+static DEFINE_SPINLOCK(umh_sysctl_lock);
+
 #ifdef CONFIG_MODULES
 
 /*
@@ -132,6 +140,7 @@
 static int ____call_usermodehelper(void *data)
 {
 	struct subprocess_info *sub_info = data;
+	struct cred *new;
 	int retval;
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -153,6 +162,19 @@
 			goto fail;
 	}
 
+	retval = -ENOMEM;
+	new = prepare_kernel_cred(current);
+	if (!new)
+		goto fail;
+
+	spin_lock(&umh_sysctl_lock);
+	new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset);
+	new->cap_inheritable = cap_intersect(usermodehelper_inheritable,
+					     new->cap_inheritable);
+	spin_unlock(&umh_sysctl_lock);
+
+	commit_creds(new);
+
 	retval = kernel_execve(sub_info->path,
 			       (const char *const *)sub_info->argv,
 			       (const char *const *)sub_info->envp);
@@ -418,6 +440,84 @@
 }
 EXPORT_SYMBOL(call_usermodehelper_exec);
 
+static int proc_cap_handler(struct ctl_table *table, int write,
+			 void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table t;
+	unsigned long cap_array[_KERNEL_CAPABILITY_U32S];
+	kernel_cap_t new_cap;
+	int err, i;
+
+	if (write && (!capable(CAP_SETPCAP) ||
+		      !capable(CAP_SYS_MODULE)))
+		return -EPERM;
+
+	/*
+	 * convert from the global kernel_cap_t to the ulong array to print to
+	 * userspace if this is a read.
+	 */
+	spin_lock(&umh_sysctl_lock);
+	for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++)  {
+		if (table->data == CAP_BSET)
+			cap_array[i] = usermodehelper_bset.cap[i];
+		else if (table->data == CAP_PI)
+			cap_array[i] = usermodehelper_inheritable.cap[i];
+		else
+			BUG();
+	}
+	spin_unlock(&umh_sysctl_lock);
+
+	t = *table;
+	t.data = &cap_array;
+
+	/*
+	 * actually read or write and array of ulongs from userspace.  Remember
+	 * these are least significant 32 bits first
+	 */
+	err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
+	if (err < 0)
+		return err;
+
+	/*
+	 * convert from the sysctl array of ulongs to the kernel_cap_t
+	 * internal representation
+	 */
+	for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++)
+		new_cap.cap[i] = cap_array[i];
+
+	/*
+	 * Drop everything not in the new_cap (but don't add things)
+	 */
+	spin_lock(&umh_sysctl_lock);
+	if (write) {
+		if (table->data == CAP_BSET)
+			usermodehelper_bset = cap_intersect(usermodehelper_bset, new_cap);
+		if (table->data == CAP_PI)
+			usermodehelper_inheritable = cap_intersect(usermodehelper_inheritable, new_cap);
+	}
+	spin_unlock(&umh_sysctl_lock);
+
+	return 0;
+}
+
+struct ctl_table usermodehelper_table[] = {
+	{
+		.procname	= "bset",
+		.data		= CAP_BSET,
+		.maxlen		= _KERNEL_CAPABILITY_U32S * sizeof(unsigned long),
+		.mode		= 0600,
+		.proc_handler	= proc_cap_handler,
+	},
+	{
+		.procname	= "inheritable",
+		.data		= CAP_PI,
+		.maxlen		= _KERNEL_CAPABILITY_U32S * sizeof(unsigned long),
+		.mode		= 0600,
+		.proc_handler	= proc_cap_handler,
+	},
+	{ }
+};
+
 void __init usermodehelper_init(void)
 {
 	khelper_wq = create_singlethread_workqueue("khelper");
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index c0bb324..965134b 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -56,6 +56,7 @@
 #include <linux/kprobes.h>
 #include <linux/pipe_fs_i.h>
 #include <linux/oom.h>
+#include <linux/kmod.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>
@@ -616,6 +617,11 @@
 		.child		= random_table,
 	},
 	{
+		.procname	= "usermodehelper",
+		.mode		= 0555,
+		.child		= usermodehelper_table,
+	},
+	{
 		.procname	= "overflowuid",
 		.data		= &overflowuid,
 		.maxlen		= sizeof(int),
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index cfa7a5e..fa000d2 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -212,10 +212,12 @@
 	int err = key->type_data.x[0];
 
 	seq_puts(m, key->description);
-	if (err)
-		seq_printf(m, ": %d", err);
-	else
-		seq_printf(m, ": %u", key->datalen);
+	if (key_is_instantiated(key)) {
+		if (err)
+			seq_printf(m, ": %d", err);
+		else
+			seq_printf(m, ": %u", key->datalen);
+	}
 }
 
 /*
diff --git a/security/Kconfig b/security/Kconfig
index 95accd4..e0f08b5 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -167,6 +167,7 @@
 config LSM_MMAP_MIN_ADDR
 	int "Low address space for LSM to protect from user allocation"
 	depends on SECURITY && SECURITY_SELINUX
+	default 32768 if ARM
 	default 65536
 	help
 	  This is the portion of low virtual memory which should be protected
diff --git a/security/commoncap.c b/security/commoncap.c
index f20e984..a93b3b7 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -529,15 +529,10 @@
 	new->suid = new->fsuid = new->euid;
 	new->sgid = new->fsgid = new->egid;
 
-	/* For init, we want to retain the capabilities set in the initial
-	 * task.  Thus we skip the usual capability rules
-	 */
-	if (!is_global_init(current)) {
-		if (effective)
-			new->cap_effective = new->cap_permitted;
-		else
-			cap_clear(new->cap_effective);
-	}
+	if (effective)
+		new->cap_effective = new->cap_permitted;
+	else
+		cap_clear(new->cap_effective);
 	bprm->cap_effective = effective;
 
 	/*
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 07a025f..f375152 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -109,11 +109,13 @@
 				    const struct cred *cred,
 				    struct key_type *type,
 				    const void *description,
-				    key_match_func_t match);
+				    key_match_func_t match,
+				    bool no_state_check);
 
 extern key_ref_t search_my_process_keyrings(struct key_type *type,
 					    const void *description,
 					    key_match_func_t match,
+					    bool no_state_check,
 					    const struct cred *cred);
 extern key_ref_t search_process_keyrings(struct key_type *type,
 					 const void *description,
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 427fddc..eca5191 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -206,8 +206,14 @@
 		goto error5;
 	}
 
+	/* wait for the key to finish being constructed */
+	ret = wait_for_key_construction(key, 1);
+	if (ret < 0)
+		goto error6;
+
 	ret = key->serial;
 
+error6:
  	key_put(key);
 error5:
 	key_type_put(ktype);
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index cdd2f3f..a06ffab 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -176,13 +176,15 @@
 	else
 		seq_puts(m, "[anon]");
 
-	rcu_read_lock();
-	klist = rcu_dereference(keyring->payload.subscriptions);
-	if (klist)
-		seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
-	else
-		seq_puts(m, ": empty");
-	rcu_read_unlock();
+	if (key_is_instantiated(keyring)) {
+		rcu_read_lock();
+		klist = rcu_dereference(keyring->payload.subscriptions);
+		if (klist)
+			seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
+		else
+			seq_puts(m, ": empty");
+		rcu_read_unlock();
+	}
 }
 
 /*
@@ -271,6 +273,7 @@
  * @type: The type of key to search for.
  * @description: Parameter for @match.
  * @match: Function to rule on whether or not a key is the one required.
+ * @no_state_check: Don't check if a matching key is bad
  *
  * Search the supplied keyring tree for a key that matches the criteria given.
  * The root keyring and any linked keyrings must grant Search permission to the
@@ -303,7 +306,8 @@
 			     const struct cred *cred,
 			     struct key_type *type,
 			     const void *description,
-			     key_match_func_t match)
+			     key_match_func_t match,
+			     bool no_state_check)
 {
 	struct {
 		struct keyring_list *keylist;
@@ -345,6 +349,8 @@
 	kflags = keyring->flags;
 	if (keyring->type == type && match(keyring, description)) {
 		key = keyring;
+		if (no_state_check)
+			goto found;
 
 		/* check it isn't negative and hasn't expired or been
 		 * revoked */
@@ -384,11 +390,13 @@
 			continue;
 
 		/* skip revoked keys and expired keys */
-		if (kflags & (1 << KEY_FLAG_REVOKED))
-			continue;
+		if (!no_state_check) {
+			if (kflags & (1 << KEY_FLAG_REVOKED))
+				continue;
 
-		if (key->expiry && now.tv_sec >= key->expiry)
-			continue;
+			if (key->expiry && now.tv_sec >= key->expiry)
+				continue;
+		}
 
 		/* keys that don't match */
 		if (!match(key, description))
@@ -399,6 +407,9 @@
 					cred, KEY_SEARCH) < 0)
 			continue;
 
+		if (no_state_check)
+			goto found;
+
 		/* we set a different error code if we pass a negative key */
 		if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
 			err = key->type_data.reject_error;
@@ -478,7 +489,7 @@
 		return ERR_PTR(-ENOKEY);
 
 	return keyring_search_aux(keyring, current->cred,
-				  type, description, type->match);
+				  type, description, type->match, false);
 }
 EXPORT_SYMBOL(keyring_search);
 
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 525cf8a..49bbc97 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -199,7 +199,7 @@
 	if (key->perm & KEY_POS_VIEW) {
 		skey_ref = search_my_process_keyrings(key->type, key,
 						      lookup_user_key_possessed,
-						      cred);
+						      true, cred);
 		if (!IS_ERR(skey_ref)) {
 			key_ref_put(skey_ref);
 			key_ref = make_key_ref(key, 1);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 930634e..6c0480d 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -331,6 +331,7 @@
 key_ref_t search_my_process_keyrings(struct key_type *type,
 				     const void *description,
 				     key_match_func_t match,
+				     bool no_state_check,
 				     const struct cred *cred)
 {
 	key_ref_t key_ref, ret, err;
@@ -350,7 +351,7 @@
 	if (cred->thread_keyring) {
 		key_ref = keyring_search_aux(
 			make_key_ref(cred->thread_keyring, 1),
-			cred, type, description, match);
+			cred, type, description, match, no_state_check);
 		if (!IS_ERR(key_ref))
 			goto found;
 
@@ -371,7 +372,7 @@
 	if (cred->tgcred->process_keyring) {
 		key_ref = keyring_search_aux(
 			make_key_ref(cred->tgcred->process_keyring, 1),
-			cred, type, description, match);
+			cred, type, description, match, no_state_check);
 		if (!IS_ERR(key_ref))
 			goto found;
 
@@ -395,7 +396,7 @@
 			make_key_ref(rcu_dereference(
 					     cred->tgcred->session_keyring),
 				     1),
-			cred, type, description, match);
+			cred, type, description, match, no_state_check);
 		rcu_read_unlock();
 
 		if (!IS_ERR(key_ref))
@@ -417,7 +418,7 @@
 	else if (cred->user->session_keyring) {
 		key_ref = keyring_search_aux(
 			make_key_ref(cred->user->session_keyring, 1),
-			cred, type, description, match);
+			cred, type, description, match, no_state_check);
 		if (!IS_ERR(key_ref))
 			goto found;
 
@@ -459,7 +460,8 @@
 
 	might_sleep();
 
-	key_ref = search_my_process_keyrings(type, description, match, cred);
+	key_ref = search_my_process_keyrings(type, description, match,
+					     false, cred);
 	if (!IS_ERR(key_ref))
 		goto found;
 	err = key_ref;
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index df3c041..b18a717 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -530,8 +530,7 @@
 	       dest_keyring, flags);
 
 	/* search all the process keyrings for a key */
-	key_ref = search_process_keyrings(type, description, type->match,
-					  cred);
+	key_ref = search_process_keyrings(type, description, type->match, cred);
 
 	if (!IS_ERR(key_ref)) {
 		key = key_ref_to_ptr(key_ref);
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 6816403..f6337c9 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -59,7 +59,8 @@
 
 	seq_puts(m, "key:");
 	seq_puts(m, key->description);
-	seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
+	if (key_is_instantiated(key))
+		seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
 }
 
 /*
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index c6ca866..63bb1aa 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -169,8 +169,8 @@
 void user_describe(const struct key *key, struct seq_file *m)
 {
 	seq_puts(m, key->description);
-
-	seq_printf(m, ": %u", key->datalen);
+	if (key_is_instantiated(key))
+		seq_printf(m, ": %u", key->datalen);
 }
 
 EXPORT_SYMBOL_GPL(user_describe);
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 7556315..a0d09e5 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -108,10 +108,9 @@
 			head->read_user_buf += len;
 			w += len;
 		}
-		if (*w) {
-			head->r.w[0] = w;
+		head->r.w[0] = w;
+		if (*w)
 			return false;
-		}
 		/* Add '\0' for query. */
 		if (head->poll) {
 			if (!head->read_user_buf_avail ||
@@ -459,8 +458,16 @@
 	if (profile == &tomoyo_default_profile)
 		return -EINVAL;
 	if (!strcmp(data, "COMMENT")) {
-		const struct tomoyo_path_info *old_comment = profile->comment;
-		profile->comment = tomoyo_get_name(cp);
+		static DEFINE_SPINLOCK(lock);
+		const struct tomoyo_path_info *new_comment
+			= tomoyo_get_name(cp);
+		const struct tomoyo_path_info *old_comment;
+		if (!new_comment)
+			return -ENOMEM;
+		spin_lock(&lock);
+		old_comment = profile->comment;
+		profile->comment = new_comment;
+		spin_unlock(&lock);
 		tomoyo_put_name(old_comment);
 		return 0;
 	}
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index cb09f1f..d64e8ec 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -1011,7 +1011,6 @@
 		break;
 	case TOMOYO_TYPE_RMDIR:
 	case TOMOYO_TYPE_CHROOT:
-	case TOMOYO_TYPE_UMOUNT:
 		tomoyo_add_slash(&buf);
 		break;
 	}
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c
index 2976126..42a7b1b 100644
--- a/security/tomoyo/memory.c
+++ b/security/tomoyo/memory.c
@@ -75,6 +75,7 @@
 		memset(data, 0, size);
 		return ptr;
 	}
+	kfree(ptr);
 	return NULL;
 }