io-wq: inherit audit loginuid and sessionid
authorJens Axboe <axboe@kernel.dk>
Thu, 15 Oct 2020 19:46:44 +0000 (13:46 -0600)
committerJens Axboe <axboe@kernel.dk>
Sat, 17 Oct 2020 15:25:47 +0000 (09:25 -0600)
Make sure the async io-wq workers inherit the loginuid and sessionid from
the original task, and restore them to unset once we're done with the
async work item.

While at it, disable the ability for kernel threads to write to their own
loginuid.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io-wq.c
fs/io_uring.c
fs/proc/base.c
include/linux/io_uring.h

index 0c852b75384db56b357cf43d448ade1a8b28cb72..7cb3b4cb9b11346e491594b4c53b8f8e41666d5a 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/fs_struct.h>
 #include <linux/task_work.h>
 #include <linux/blk-cgroup.h>
+#include <linux/audit.h>
 
 #include "io-wq.h"
 
@@ -484,6 +485,10 @@ static void io_impersonate_work(struct io_worker *worker,
                io_wq_switch_creds(worker, work);
        current->signal->rlim[RLIMIT_FSIZE].rlim_cur = work->identity->fsize;
        io_wq_switch_blkcg(worker, work);
+#ifdef CONFIG_AUDIT
+       current->loginuid = work->identity->loginuid;
+       current->sessionid = work->identity->sessionid;
+#endif
 }
 
 static void io_assign_current_work(struct io_worker *worker,
@@ -496,6 +501,11 @@ static void io_assign_current_work(struct io_worker *worker,
                cond_resched();
        }
 
+#ifdef CONFIG_AUDIT
+       current->loginuid = KUIDT_INIT(AUDIT_UID_UNSET);
+       current->sessionid = AUDIT_SID_UNSET;
+#endif
+
        spin_lock_irq(&worker->lock);
        worker->cur_work = work;
        spin_unlock_irq(&worker->lock);
index 58c445b95085278b791920db20ad3e56d6068242..b9ffe98f18bc9b9803e007bc8362b6352c411a4d 100644 (file)
@@ -81,6 +81,7 @@
 #include <linux/pagemap.h>
 #include <linux/io_uring.h>
 #include <linux/blk-cgroup.h>
+#include <linux/audit.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/io_uring.h>
@@ -327,6 +328,11 @@ struct io_ring_ctx {
 
        const struct cred       *creds;
 
+#ifdef CONFIG_AUDIT
+       kuid_t                  loginuid;
+       unsigned int            sessionid;
+#endif
+
        struct completion       ref_comp;
        struct completion       sq_thread_comp;
 
@@ -1057,6 +1063,10 @@ static void io_init_identity(struct io_identity *id)
        id->nsproxy = current->nsproxy;
        id->fs = current->fs;
        id->fsize = rlimit(RLIMIT_FSIZE);
+#ifdef CONFIG_AUDIT
+       id->loginuid = current->loginuid;
+       id->sessionid = current->sessionid;
+#endif
        refcount_set(&id->count, 1);
 }
 
@@ -1316,6 +1326,11 @@ static bool io_grab_identity(struct io_kiocb *req)
                get_cred(id->creds);
                req->work.flags |= IO_WQ_WORK_CREDS;
        }
+#ifdef CONFIG_AUDIT
+       if (!uid_eq(current->loginuid, id->loginuid) ||
+           current->sessionid != id->sessionid)
+               return false;
+#endif
        if (!(req->work.flags & IO_WQ_WORK_FS) &&
            (def->work_flags & IO_WQ_WORK_FS)) {
                if (current->fs != id->fs)
@@ -6755,6 +6770,10 @@ static int io_sq_thread(void *data)
                                old_cred = override_creds(ctx->creds);
                        }
                        io_sq_thread_associate_blkcg(ctx, &cur_css);
+#ifdef CONFIG_AUDIT
+                       current->loginuid = ctx->loginuid;
+                       current->sessionid = ctx->sessionid;
+#endif
 
                        ret |= __io_sq_thread(ctx, start_jiffies, cap_entries);
 
@@ -9203,7 +9222,10 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p,
        ctx->compat = in_compat_syscall();
        ctx->user = user;
        ctx->creds = get_current_cred();
-
+#ifdef CONFIG_AUDIT
+       ctx->loginuid = current->loginuid;
+       ctx->sessionid = current->sessionid;
+#endif
        ctx->sqo_task = get_task_struct(current);
 
        /*
index aa69c35d904cae01dbbbf3004fac30470964c37c..0f707003dda53fb722f6566b2d3a9eb69c386d9a 100644 (file)
@@ -1268,6 +1268,10 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
        kuid_t kloginuid;
        int rv;
 
+       /* Don't let kthreads write their own loginuid */
+       if (current->flags & PF_KTHREAD)
+               return -EPERM;
+
        rcu_read_lock();
        if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) {
                rcu_read_unlock();
index 28939820b6b0349633ce08c2199fd1c882587a23..868364cea3b740429a7ca4e84337b7ad79846956 100644 (file)
@@ -15,6 +15,10 @@ struct io_identity {
        struct nsproxy                  *nsproxy;
        struct fs_struct                *fs;
        unsigned long                   fsize;
+#ifdef CONFIG_AUDIT
+       kuid_t                          loginuid;
+       unsigned int                    sessionid;
+#endif
        refcount_t                      count;
 };