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 0c852b7..7cb3b4c 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 58c445b..b9ffe98 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 aa69c35..0f70700 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 2893982..868364c 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;
 };