aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSerge Hallyn <serue@us.ibm.com>2008-10-15 17:38:45 -0400
committerSerge E. Hallyn <serue@us.ibm.com>2008-11-24 18:57:41 -0500
commit18b6e0414e42d95183f07d8177e3ff0241abd825 (patch)
tree91ca2f2d442055e31eb7bb551bf7060f3f4c4cc7 /fs
parent9789cfe22e5d7bc10cad841a4ea96ecedb34b267 (diff)
User namespaces: set of cleanups (v2)
The user_ns is moved from nsproxy to user_struct, so that a struct cred by itself is sufficient to determine access (which it otherwise would not be). Corresponding ecryptfs fixes (by David Howells) are here as well. Fix refcounting. The following rules now apply: 1. The task pins the user struct. 2. The user struct pins its user namespace. 3. The user namespace pins the struct user which created it. User namespaces are cloned during copy_creds(). Unsharing a new user_ns is no longer possible. (We could re-add that, but it'll cause code duplication and doesn't seem useful if PAM doesn't need to clone user namespaces). When a user namespace is created, its first user (uid 0) gets empty keyrings and a clean group_info. This incorporates a previous patch by David Howells. Here is his original patch description: >I suggest adding the attached incremental patch. It makes the following >changes: > > (1) Provides a current_user_ns() macro to wrap accesses to current's user > namespace. > > (2) Fixes eCryptFS. > > (3) Renames create_new_userns() to create_user_ns() to be more consistent > with the other associated functions and because the 'new' in the name is > superfluous. > > (4) Moves the argument and permission checks made for CLONE_NEWUSER to the > beginning of do_fork() so that they're done prior to making any attempts > at allocation. > > (5) Calls create_user_ns() after prepare_creds(), and gives it the new creds > to fill in rather than have it return the new root user. I don't imagine > the new root user being used for anything other than filling in a cred > struct. > > This also permits me to get rid of a get_uid() and a free_uid(), as the > reference the creds were holding on the old user_struct can just be > transferred to the new namespace's creator pointer. > > (6) Makes create_user_ns() reset the UIDs and GIDs of the creds under > preparation rather than doing it in copy_creds(). > >David >Signed-off-by: David Howells <dhowells@redhat.com> Changelog: Oct 20: integrate dhowells comments 1. leave thread_keyring alone 2. use current_user_ns() in set_user() Signed-off-by: Serge Hallyn <serue@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ecryptfs/messaging.c13
-rw-r--r--fs/ecryptfs/miscdev.c19
2 files changed, 13 insertions, 19 deletions
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
index e0b0a4e28b9b..6913f727624d 100644
--- a/fs/ecryptfs/messaging.c
+++ b/fs/ecryptfs/messaging.c
@@ -360,7 +360,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
360 struct ecryptfs_msg_ctx *msg_ctx; 360 struct ecryptfs_msg_ctx *msg_ctx;
361 size_t msg_size; 361 size_t msg_size;
362 struct nsproxy *nsproxy; 362 struct nsproxy *nsproxy;
363 struct user_namespace *current_user_ns; 363 struct user_namespace *tsk_user_ns;
364 uid_t ctx_euid; 364 uid_t ctx_euid;
365 int rc; 365 int rc;
366 366
@@ -385,9 +385,9 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
385 mutex_unlock(&ecryptfs_daemon_hash_mux); 385 mutex_unlock(&ecryptfs_daemon_hash_mux);
386 goto wake_up; 386 goto wake_up;
387 } 387 }
388 current_user_ns = nsproxy->user_ns; 388 tsk_user_ns = __task_cred(msg_ctx->task)->user->user_ns;
389 ctx_euid = task_euid(msg_ctx->task); 389 ctx_euid = task_euid(msg_ctx->task);
390 rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, current_user_ns); 390 rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns);
391 rcu_read_unlock(); 391 rcu_read_unlock();
392 mutex_unlock(&ecryptfs_daemon_hash_mux); 392 mutex_unlock(&ecryptfs_daemon_hash_mux);
393 if (rc) { 393 if (rc) {
@@ -405,11 +405,11 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
405 euid, ctx_euid); 405 euid, ctx_euid);
406 goto unlock; 406 goto unlock;
407 } 407 }
408 if (current_user_ns != user_ns) { 408 if (tsk_user_ns != user_ns) {
409 rc = -EBADMSG; 409 rc = -EBADMSG;
410 printk(KERN_WARNING "%s: Received message from user_ns " 410 printk(KERN_WARNING "%s: Received message from user_ns "
411 "[0x%p]; expected message from user_ns [0x%p]\n", 411 "[0x%p]; expected message from user_ns [0x%p]\n",
412 __func__, user_ns, nsproxy->user_ns); 412 __func__, user_ns, tsk_user_ns);
413 goto unlock; 413 goto unlock;
414 } 414 }
415 if (daemon->pid != pid) { 415 if (daemon->pid != pid) {
@@ -468,8 +468,7 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type,
468 uid_t euid = current_euid(); 468 uid_t euid = current_euid();
469 int rc; 469 int rc;
470 470
471 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, 471 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
472 current->nsproxy->user_ns);
473 if (rc || !daemon) { 472 if (rc || !daemon) {
474 rc = -ENOTCONN; 473 rc = -ENOTCONN;
475 printk(KERN_ERR "%s: User [%d] does not have a daemon " 474 printk(KERN_ERR "%s: User [%d] does not have a daemon "
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 047ac609695b..efd95a0ed1ea 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -47,8 +47,7 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
47 47
48 mutex_lock(&ecryptfs_daemon_hash_mux); 48 mutex_lock(&ecryptfs_daemon_hash_mux);
49 /* TODO: Just use file->private_data? */ 49 /* TODO: Just use file->private_data? */
50 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, 50 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
51 current->nsproxy->user_ns);
52 BUG_ON(rc || !daemon); 51 BUG_ON(rc || !daemon);
53 mutex_lock(&daemon->mux); 52 mutex_lock(&daemon->mux);
54 mutex_unlock(&ecryptfs_daemon_hash_mux); 53 mutex_unlock(&ecryptfs_daemon_hash_mux);
@@ -95,11 +94,9 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
95 "count; rc = [%d]\n", __func__, rc); 94 "count; rc = [%d]\n", __func__, rc);
96 goto out_unlock_daemon_list; 95 goto out_unlock_daemon_list;
97 } 96 }
98 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, 97 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
99 current->nsproxy->user_ns);
100 if (rc || !daemon) { 98 if (rc || !daemon) {
101 rc = ecryptfs_spawn_daemon(&daemon, euid, 99 rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(),
102 current->nsproxy->user_ns,
103 task_pid(current)); 100 task_pid(current));
104 if (rc) { 101 if (rc) {
105 printk(KERN_ERR "%s: Error attempting to spawn daemon; " 102 printk(KERN_ERR "%s: Error attempting to spawn daemon; "
@@ -153,8 +150,7 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)
153 int rc; 150 int rc;
154 151
155 mutex_lock(&ecryptfs_daemon_hash_mux); 152 mutex_lock(&ecryptfs_daemon_hash_mux);
156 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, 153 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
157 current->nsproxy->user_ns);
158 BUG_ON(rc || !daemon); 154 BUG_ON(rc || !daemon);
159 mutex_lock(&daemon->mux); 155 mutex_lock(&daemon->mux);
160 BUG_ON(daemon->pid != task_pid(current)); 156 BUG_ON(daemon->pid != task_pid(current));
@@ -254,8 +250,7 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
254 250
255 mutex_lock(&ecryptfs_daemon_hash_mux); 251 mutex_lock(&ecryptfs_daemon_hash_mux);
256 /* TODO: Just use file->private_data? */ 252 /* TODO: Just use file->private_data? */
257 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, 253 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
258 current->nsproxy->user_ns);
259 BUG_ON(rc || !daemon); 254 BUG_ON(rc || !daemon);
260 mutex_lock(&daemon->mux); 255 mutex_lock(&daemon->mux);
261 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { 256 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
@@ -295,7 +290,7 @@ check_list:
295 goto check_list; 290 goto check_list;
296 } 291 }
297 BUG_ON(euid != daemon->euid); 292 BUG_ON(euid != daemon->euid);
298 BUG_ON(current->nsproxy->user_ns != daemon->user_ns); 293 BUG_ON(current_user_ns() != daemon->user_ns);
299 BUG_ON(task_pid(current) != daemon->pid); 294 BUG_ON(task_pid(current) != daemon->pid);
300 msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue, 295 msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
301 struct ecryptfs_msg_ctx, daemon_out_list); 296 struct ecryptfs_msg_ctx, daemon_out_list);
@@ -468,7 +463,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
468 goto out_free; 463 goto out_free;
469 } 464 }
470 rc = ecryptfs_miscdev_response(&data[i], packet_size, 465 rc = ecryptfs_miscdev_response(&data[i], packet_size,
471 euid, current->nsproxy->user_ns, 466 euid, current_user_ns(),
472 task_pid(current), seq); 467 task_pid(current), seq);
473 if (rc) 468 if (rc)
474 printk(KERN_WARNING "%s: Failed to deliver miscdev " 469 printk(KERN_WARNING "%s: Failed to deliver miscdev "