summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorTao Huang <huangtao@rock-chips.com>2017-11-02 17:00:07 +0800
committerTao Huang <huangtao@rock-chips.com>2017-11-02 17:00:07 +0800
commit6bedca442a1780bcc68d92bfb243d5b49e1c6974 (patch)
tree684afe556166bb253d756d10570b0e86dd9a2b91 /security
parent7976ad8228d6783dcc3ce60d44283f321af4add8 (diff)
parentce6cd7bc4af7e1c83b8a87cb1f4639b7fd75dc15 (diff)
Merge branch 'linux-linaro-lsk-v4.4-android' of git://git.linaro.org/kernel/linux-linaro-stable.git
* linux-linaro-lsk-v4.4-android: (546 commits) Linux 4.4.93 x86/alternatives: Fix alt_max_short macro to really be a max() USB: serial: console: fix use-after-free after failed setup USB: serial: qcserial: add Dell DW5818, DW5819 USB: serial: option: add support for TP-Link LTE module USB: serial: cp210x: add support for ELV TFD500 USB: serial: ftdi_sio: add id for Cypress WICED dev board fix unbalanced page refcounting in bio_map_user_iov direct-io: Prevent NULL pointer access in submit_page_section usb: gadget: composite: Fix use-after-free in usb_composite_overwrite_options ALSA: line6: Fix leftover URB at error-path during probe ALSA: caiaq: Fix stray URB at probe error path ALSA: seq: Fix copy_from_user() call inside lock ALSA: seq: Fix use-after-free at creating a port ALSA: usb-audio: Kill stray URB at exiting iommu/amd: Finish TLB flush in amd_iommu_unmap() usb: renesas_usbhs: Fix DMAC sequence for receiving zero-length packet KVM: nVMX: fix guest CR4 loading when emulating L2 to L1 exit crypto: shash - Fix zero-length shash ahash digest crash HID: usbhid: fix out-of-bounds bug ... Conflicts: drivers/cpufreq/cpufreq-dt.c drivers/usb/dwc3/gadget.c Change-Id: I1a24ad0bba307b56b5ddf1fd7c4832ffb73ad12f
Diffstat (limited to 'security')
-rw-r--r--security/keys/internal.h2
-rw-r--r--security/keys/key.c2
-rw-r--r--security/keys/keyctl.c5
-rw-r--r--security/keys/keyring.c37
-rw-r--r--security/keys/process_keys.c8
-rw-r--r--security/smack/smack_lsm.c55
6 files changed, 58 insertions, 51 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 5105c2c2da75..51ffb9cde073 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -136,7 +136,7 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
extern key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx);
extern key_ref_t search_process_keyrings(struct keyring_search_context *ctx);
-extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
+extern struct key *find_keyring_by_name(const char *name, bool uid_keyring);
extern int install_user_keyrings(void);
extern int install_thread_keyring_to_cred(struct cred *);
diff --git a/security/keys/key.c b/security/keys/key.c
index 09c10b181881..51d23c623424 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -296,6 +296,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->flags |= 1 << KEY_FLAG_IN_QUOTA;
if (flags & KEY_ALLOC_TRUSTED)
key->flags |= 1 << KEY_FLAG_TRUSTED;
+ if (flags & KEY_ALLOC_UID_KEYRING)
+ key->flags |= 1 << KEY_FLAG_UID_KEYRING;
#ifdef KEY_DEBUGGING
key->magic = KEY_DEBUG_MAGIC;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 671709d8610d..a009dc66eb8f 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -738,6 +738,11 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
key = key_ref_to_ptr(key_ref);
+ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
+ ret = -ENOKEY;
+ goto error2;
+ }
+
/* see if we can read it directly */
ret = key_permission(key_ref, KEY_NEED_READ);
if (ret == 0)
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index f931ccfeefb0..0c8dd4fbe130 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -416,7 +416,7 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m)
}
struct keyring_read_iterator_context {
- size_t qty;
+ size_t buflen;
size_t count;
key_serial_t __user *buffer;
};
@@ -428,9 +428,9 @@ static int keyring_read_iterator(const void *object, void *data)
int ret;
kenter("{%s,%d},,{%zu/%zu}",
- key->type->name, key->serial, ctx->count, ctx->qty);
+ key->type->name, key->serial, ctx->count, ctx->buflen);
- if (ctx->count >= ctx->qty)
+ if (ctx->count >= ctx->buflen)
return 1;
ret = put_user(key->serial, ctx->buffer);
@@ -465,16 +465,12 @@ static long keyring_read(const struct key *keyring,
return 0;
/* Calculate how much data we could return */
- ctx.qty = nr_keys * sizeof(key_serial_t);
-
if (!buffer || !buflen)
- return ctx.qty;
-
- if (buflen > ctx.qty)
- ctx.qty = buflen;
+ return nr_keys * sizeof(key_serial_t);
/* Copy the IDs of the subscribed keys into the buffer */
ctx.buffer = (key_serial_t __user *)buffer;
+ ctx.buflen = buflen;
ctx.count = 0;
ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx);
if (ret < 0) {
@@ -965,15 +961,15 @@ found:
/*
* Find a keyring with the specified name.
*
- * All named keyrings in the current user namespace are searched, provided they
- * grant Search permission directly to the caller (unless this check is
- * skipped). Keyrings whose usage points have reached zero or who have been
- * revoked are skipped.
+ * Only keyrings that have nonzero refcount, are not revoked, and are owned by a
+ * user in the current user namespace are considered. If @uid_keyring is %true,
+ * the keyring additionally must have been allocated as a user or user session
+ * keyring; otherwise, it must grant Search permission directly to the caller.
*
* Returns a pointer to the keyring with the keyring's refcount having being
* incremented on success. -ENOKEY is returned if a key could not be found.
*/
-struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
+struct key *find_keyring_by_name(const char *name, bool uid_keyring)
{
struct key *keyring;
int bucket;
@@ -1001,10 +997,15 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
if (strcmp(keyring->description, name) != 0)
continue;
- if (!skip_perm_check &&
- key_permission(make_key_ref(keyring, 0),
- KEY_NEED_SEARCH) < 0)
- continue;
+ if (uid_keyring) {
+ if (!test_bit(KEY_FLAG_UID_KEYRING,
+ &keyring->flags))
+ continue;
+ } else {
+ if (key_permission(make_key_ref(keyring, 0),
+ KEY_NEED_SEARCH) < 0)
+ continue;
+ }
/* we've got a match but we might end up racing with
* key_cleanup() if the keyring is currently 'dead'
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 4ed909142956..7dd050f24261 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -76,7 +76,9 @@ int install_user_keyrings(void)
if (IS_ERR(uid_keyring)) {
uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID,
cred, user_keyring_perm,
- KEY_ALLOC_IN_QUOTA, NULL);
+ KEY_ALLOC_UID_KEYRING |
+ KEY_ALLOC_IN_QUOTA,
+ NULL);
if (IS_ERR(uid_keyring)) {
ret = PTR_ERR(uid_keyring);
goto error;
@@ -92,7 +94,9 @@ int install_user_keyrings(void)
session_keyring =
keyring_alloc(buf, user->uid, INVALID_GID,
cred, user_keyring_perm,
- KEY_ALLOC_IN_QUOTA, NULL);
+ KEY_ALLOC_UID_KEYRING |
+ KEY_ALLOC_IN_QUOTA,
+ NULL);
if (IS_ERR(session_keyring)) {
ret = PTR_ERR(session_keyring);
goto error_release;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 7c57c7fcf5a2..735a1a9386d6 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1459,7 +1459,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
* @inode: the object
* @name: attribute name
* @buffer: where to put the result
- * @alloc: unused
+ * @alloc: duplicate memory
*
* Returns the size of the attribute or an error code
*/
@@ -1472,43 +1472,38 @@ static int smack_inode_getsecurity(const struct inode *inode,
struct super_block *sbp;
struct inode *ip = (struct inode *)inode;
struct smack_known *isp;
- int ilen;
- int rc = 0;
- if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
+ if (strcmp(name, XATTR_SMACK_SUFFIX) == 0)
isp = smk_of_inode(inode);
- ilen = strlen(isp->smk_known);
- *buffer = isp->smk_known;
- return ilen;
- }
+ else {
+ /*
+ * The rest of the Smack xattrs are only on sockets.
+ */
+ sbp = ip->i_sb;
+ if (sbp->s_magic != SOCKFS_MAGIC)
+ return -EOPNOTSUPP;
- /*
- * The rest of the Smack xattrs are only on sockets.
- */
- sbp = ip->i_sb;
- if (sbp->s_magic != SOCKFS_MAGIC)
- return -EOPNOTSUPP;
+ sock = SOCKET_I(ip);
+ if (sock == NULL || sock->sk == NULL)
+ return -EOPNOTSUPP;
- sock = SOCKET_I(ip);
- if (sock == NULL || sock->sk == NULL)
- return -EOPNOTSUPP;
-
- ssp = sock->sk->sk_security;
+ ssp = sock->sk->sk_security;
- if (strcmp(name, XATTR_SMACK_IPIN) == 0)
- isp = ssp->smk_in;
- else if (strcmp(name, XATTR_SMACK_IPOUT) == 0)
- isp = ssp->smk_out;
- else
- return -EOPNOTSUPP;
+ if (strcmp(name, XATTR_SMACK_IPIN) == 0)
+ isp = ssp->smk_in;
+ else if (strcmp(name, XATTR_SMACK_IPOUT) == 0)
+ isp = ssp->smk_out;
+ else
+ return -EOPNOTSUPP;
+ }
- ilen = strlen(isp->smk_known);
- if (rc == 0) {
- *buffer = isp->smk_known;
- rc = ilen;
+ if (alloc) {
+ *buffer = kstrdup(isp->smk_known, GFP_KERNEL);
+ if (*buffer == NULL)
+ return -ENOMEM;
}
- return rc;
+ return strlen(isp->smk_known);
}