Commit 78ee8b1b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull security subsystem updates from James Morris:
 "Just a few bugfixes and documentation updates"

* 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  seccomp: fix up grammar in comment
  Revert "security: inode: fix a missing check for securityfs_create_file"
  Yama: mark function as static
  security: inode: fix a missing check for securityfs_create_file
  keys: safe concurrent user->{session,uid}_keyring access
  security: don't use RCU accessors for cred->session_keyring
  Yama: mark local symbols as static
  LSM: lsm_hooks.h: fix documentation format
  LSM: fix documentation for the shm_* hooks
  LSM: fix documentation for the sem_* hooks
  LSM: fix documentation for the msg_queue_* hooks
  LSM: fix documentation for the audit_* hooks
  LSM: fix documentation for the path_chmod hook
  LSM: fix documentation for the socket_getpeersec_dgram hook
  LSM: fix documentation for the task_setscheduler hook
  LSM: fix documentation for the socket_post_create hook
  LSM: fix documentation for the syslog hook
  LSM: fix documentation for sb_copy_data hook
parents 9bff9dfc 6beff00b
...@@ -138,7 +138,7 @@ struct cred { ...@@ -138,7 +138,7 @@ struct cred {
#ifdef CONFIG_KEYS #ifdef CONFIG_KEYS
unsigned char jit_keyring; /* default keyring to attach requested unsigned char jit_keyring; /* default keyring to attach requested
* keys to */ * keys to */
struct key __rcu *session_keyring; /* keyring inherited over fork */ struct key *session_keyring; /* keyring inherited over fork */
struct key *process_keyring; /* keyring private to this process */ struct key *process_keyring; /* keyring private to this process */
struct key *thread_keyring; /* keyring private to this thread */ struct key *thread_keyring; /* keyring private to this thread */
struct key *request_key_auth; /* assumed request_key authority */ struct key *request_key_auth; /* assumed request_key authority */
......
This diff is collapsed.
...@@ -31,6 +31,13 @@ struct user_struct { ...@@ -31,6 +31,13 @@ struct user_struct {
atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */
#ifdef CONFIG_KEYS #ifdef CONFIG_KEYS
/*
* These pointers can only change from NULL to a non-NULL value once.
* Writes are protected by key_user_keyring_mutex.
* Unlocked readers should use READ_ONCE() unless they know that
* install_user_keyrings() has been called successfully (which sets
* these members to non-NULL values, preventing further modifications).
*/
struct key *uid_keyring; /* UID specific keyring */ struct key *uid_keyring; /* UID specific keyring */
struct key *session_keyring; /* UID's default session keyring */ struct key *session_keyring; /* UID's default session keyring */
#endif #endif
......
...@@ -331,7 +331,7 @@ static int is_ancestor(struct seccomp_filter *parent, ...@@ -331,7 +331,7 @@ static int is_ancestor(struct seccomp_filter *parent,
* Expects sighand and cred_guard_mutex locks to be held. * Expects sighand and cred_guard_mutex locks to be held.
* *
* Returns 0 on success, -ve on error, or the pid of a thread which was * Returns 0 on success, -ve on error, or the pid of a thread which was
* either not in the correct seccomp mode or it did not have an ancestral * either not in the correct seccomp mode or did not have an ancestral
* seccomp filter. * seccomp filter.
*/ */
static inline pid_t seccomp_can_sync_threads(void) static inline pid_t seccomp_can_sync_threads(void)
......
...@@ -58,7 +58,7 @@ int install_user_keyrings(void) ...@@ -58,7 +58,7 @@ int install_user_keyrings(void)
kenter("%p{%u}", user, uid); kenter("%p{%u}", user, uid);
if (user->uid_keyring && user->session_keyring) { if (READ_ONCE(user->uid_keyring) && READ_ONCE(user->session_keyring)) {
kleave(" = 0 [exist]"); kleave(" = 0 [exist]");
return 0; return 0;
} }
...@@ -111,8 +111,10 @@ int install_user_keyrings(void) ...@@ -111,8 +111,10 @@ int install_user_keyrings(void)
} }
/* install the keyrings */ /* install the keyrings */
user->uid_keyring = uid_keyring; /* paired with READ_ONCE() */
user->session_keyring = session_keyring; smp_store_release(&user->uid_keyring, uid_keyring);
/* paired with READ_ONCE() */
smp_store_release(&user->session_keyring, session_keyring);
} }
mutex_unlock(&key_user_keyring_mutex); mutex_unlock(&key_user_keyring_mutex);
...@@ -227,6 +229,7 @@ static int install_process_keyring(void) ...@@ -227,6 +229,7 @@ static int install_process_keyring(void)
* Install the given keyring as the session keyring of the given credentials * Install the given keyring as the session keyring of the given credentials
* struct, replacing the existing one if any. If the given keyring is NULL, * struct, replacing the existing one if any. If the given keyring is NULL,
* then install a new anonymous session keyring. * then install a new anonymous session keyring.
* @cred can not be in use by any task yet.
* *
* Return: 0 on success; -errno on failure. * Return: 0 on success; -errno on failure.
*/ */
...@@ -254,7 +257,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) ...@@ -254,7 +257,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
/* install the keyring */ /* install the keyring */
old = cred->session_keyring; old = cred->session_keyring;
rcu_assign_pointer(cred->session_keyring, keyring); cred->session_keyring = keyring;
if (old) if (old)
key_put(old); key_put(old);
...@@ -339,6 +342,7 @@ void key_fsgid_changed(struct task_struct *tsk) ...@@ -339,6 +342,7 @@ void key_fsgid_changed(struct task_struct *tsk)
key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
{ {
key_ref_t key_ref, ret, err; key_ref_t key_ref, ret, err;
const struct cred *cred = ctx->cred;
/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
* searchable, but we failed to find a key or we found a negative key; * searchable, but we failed to find a key or we found a negative key;
...@@ -352,9 +356,9 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) ...@@ -352,9 +356,9 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
err = ERR_PTR(-EAGAIN); err = ERR_PTR(-EAGAIN);
/* search the thread keyring first */ /* search the thread keyring first */
if (ctx->cred->thread_keyring) { if (cred->thread_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(ctx->cred->thread_keyring, 1), ctx); make_key_ref(cred->thread_keyring, 1), ctx);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -370,9 +374,9 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) ...@@ -370,9 +374,9 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
} }
/* search the process keyring second */ /* search the process keyring second */
if (ctx->cred->process_keyring) { if (cred->process_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(ctx->cred->process_keyring, 1), ctx); make_key_ref(cred->process_keyring, 1), ctx);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -391,12 +395,9 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) ...@@ -391,12 +395,9 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
} }
/* search the session keyring */ /* search the session keyring */
if (ctx->cred->session_keyring) { if (cred->session_keyring) {
rcu_read_lock();
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(rcu_dereference(ctx->cred->session_keyring), 1), make_key_ref(cred->session_keyring, 1), ctx);
ctx);
rcu_read_unlock();
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -415,9 +416,9 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) ...@@ -415,9 +416,9 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
} }
} }
/* or search the user-session keyring */ /* or search the user-session keyring */
else if (ctx->cred->user->session_keyring) { else if (READ_ONCE(cred->user->session_keyring)) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(ctx->cred->user->session_keyring, 1), make_key_ref(READ_ONCE(cred->user->session_keyring), 1),
ctx); ctx);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -604,7 +605,7 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, ...@@ -604,7 +605,7 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
goto error; goto error;
goto reget_creds; goto reget_creds;
} else if (ctx.cred->session_keyring == } else if (ctx.cred->session_keyring ==
ctx.cred->user->session_keyring && READ_ONCE(ctx.cred->user->session_keyring) &&
lflags & KEY_LOOKUP_CREATE) { lflags & KEY_LOOKUP_CREATE) {
ret = join_session_keyring(NULL); ret = join_session_keyring(NULL);
if (ret < 0) if (ret < 0)
...@@ -612,15 +613,13 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, ...@@ -612,15 +613,13 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
goto reget_creds; goto reget_creds;
} }
rcu_read_lock(); key = ctx.cred->session_keyring;
key = rcu_dereference(ctx.cred->session_keyring);
__key_get(key); __key_get(key);
rcu_read_unlock();
key_ref = make_key_ref(key, 1); key_ref = make_key_ref(key, 1);
break; break;
case KEY_SPEC_USER_KEYRING: case KEY_SPEC_USER_KEYRING:
if (!ctx.cred->user->uid_keyring) { if (!READ_ONCE(ctx.cred->user->uid_keyring)) {
ret = install_user_keyrings(); ret = install_user_keyrings();
if (ret < 0) if (ret < 0)
goto error; goto error;
...@@ -632,7 +631,7 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, ...@@ -632,7 +631,7 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
break; break;
case KEY_SPEC_USER_SESSION_KEYRING: case KEY_SPEC_USER_SESSION_KEYRING:
if (!ctx.cred->user->session_keyring) { if (!READ_ONCE(ctx.cred->user->session_keyring)) {
ret = install_user_keyrings(); ret = install_user_keyrings();
if (ret < 0) if (ret < 0)
goto error; goto error;
......
...@@ -142,12 +142,10 @@ static int call_sbin_request_key(struct key *authkey, void *aux) ...@@ -142,12 +142,10 @@ static int call_sbin_request_key(struct key *authkey, void *aux)
prkey = cred->process_keyring->serial; prkey = cred->process_keyring->serial;
sprintf(keyring_str[1], "%d", prkey); sprintf(keyring_str[1], "%d", prkey);
rcu_read_lock(); session = cred->session_keyring;
session = rcu_dereference(cred->session_keyring);
if (!session) if (!session)
session = cred->user->session_keyring; session = cred->user->session_keyring;
sskey = session->serial; sskey = session->serial;
rcu_read_unlock();
sprintf(keyring_str[2], "%d", sskey); sprintf(keyring_str[2], "%d", sskey);
...@@ -287,10 +285,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring) ...@@ -287,10 +285,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring)
/* fall through */ /* fall through */
case KEY_REQKEY_DEFL_SESSION_KEYRING: case KEY_REQKEY_DEFL_SESSION_KEYRING:
rcu_read_lock(); dest_keyring = key_get(cred->session_keyring);
dest_keyring = key_get(
rcu_dereference(cred->session_keyring));
rcu_read_unlock();
if (dest_keyring) if (dest_keyring)
break; break;
...@@ -298,11 +293,12 @@ static int construct_get_dest_keyring(struct key **_dest_keyring) ...@@ -298,11 +293,12 @@ static int construct_get_dest_keyring(struct key **_dest_keyring)
/* fall through */ /* fall through */
case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
dest_keyring = dest_keyring =
key_get(cred->user->session_keyring); key_get(READ_ONCE(cred->user->session_keyring));
break; break;
case KEY_REQKEY_DEFL_USER_KEYRING: case KEY_REQKEY_DEFL_USER_KEYRING:
dest_keyring = key_get(cred->user->uid_keyring); dest_keyring =
key_get(READ_ONCE(cred->user->uid_keyring));
break; break;
case KEY_REQKEY_DEFL_GROUP_KEYRING: case KEY_REQKEY_DEFL_GROUP_KEYRING:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment