Skip to content

Commit 0093ccb

Browse files
committed
cred: Refcount the user_ns pointed to by the cred.
struct user_struct will shortly loose it's user_ns reference so make the cred user_ns reference a proper reference complete with reference counting. Acked-by: Serge Hallyn <[email protected]> Signed-off-by: Eric W. Biederman <[email protected]>
1 parent c4a4d60 commit 0093ccb

File tree

4 files changed

+10
-10
lines changed

4 files changed

+10
-10
lines changed

include/linux/cred.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ struct cred {
146146
void *security; /* subjective LSM security */
147147
#endif
148148
struct user_struct *user; /* real user ID subscription */
149-
struct user_namespace *user_ns; /* cached user->user_ns */
149+
struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
150150
struct group_info *group_info; /* supplementary groups for euid/fsgid */
151151
struct rcu_head rcu; /* RCU deletion hook */
152152
};

kernel/cred.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ static void put_cred_rcu(struct rcu_head *rcu)
148148
if (cred->group_info)
149149
put_group_info(cred->group_info);
150150
free_uid(cred->user);
151+
put_user_ns(cred->user_ns);
151152
kmem_cache_free(cred_jar, cred);
152153
}
153154

@@ -303,6 +304,7 @@ struct cred *prepare_creds(void)
303304
set_cred_subscribers(new, 0);
304305
get_group_info(new->group_info);
305306
get_uid(new->user);
307+
get_user_ns(new->user_ns);
306308

307309
#ifdef CONFIG_KEYS
308310
key_get(new->thread_keyring);
@@ -412,11 +414,6 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
412414
goto error_put;
413415
}
414416

415-
/* cache user_ns in cred. Doesn't need a refcount because it will
416-
* stay pinned by cred->user
417-
*/
418-
new->user_ns = new->user->user_ns;
419-
420417
#ifdef CONFIG_KEYS
421418
/* new threads get their own thread keyrings if their parent already
422419
* had one */
@@ -676,6 +673,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
676673
atomic_set(&new->usage, 1);
677674
set_cred_subscribers(new, 0);
678675
get_uid(new->user);
676+
get_user_ns(new->user_ns);
679677
get_group_info(new->group_info);
680678

681679
#ifdef CONFIG_KEYS

kernel/user_namespace.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ static struct kmem_cache *user_ns_cachep __read_mostly;
2424
*/
2525
int create_user_ns(struct cred *new)
2626
{
27-
struct user_namespace *ns;
27+
struct user_namespace *ns, *parent_ns = new->user_ns;
2828
struct user_struct *root_user;
2929
int n;
3030

@@ -57,8 +57,10 @@ int create_user_ns(struct cred *new)
5757
#endif
5858
/* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */
5959

60-
/* root_user holds a reference to ns, our reference can be dropped */
61-
put_user_ns(ns);
60+
/* Leave the reference to our user_ns with the new cred */
61+
new->user_ns = ns;
62+
63+
put_user_ns(parent_ns);
6264

6365
return 0;
6466
}

security/keys/process_keys.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ void key_replace_session_keyring(void)
858858
new-> sgid = old-> sgid;
859859
new->fsgid = old->fsgid;
860860
new->user = get_uid(old->user);
861-
new->user_ns = new->user_ns;
861+
new->user_ns = get_user_ns(new->user_ns);
862862
new->group_info = get_group_info(old->group_info);
863863

864864
new->securebits = old->securebits;

0 commit comments

Comments
 (0)