On Mon, Oct 9, 2023 at 1:51 PM Paul Moore <p...@paul-moore.com> wrote:
> On Mon, Oct 9, 2023 at 1:41 PM John Johansen
> <john.johan...@canonical.com> wrote:
> > On 10/9/23 10:06, Paul Moore wrote:
> > > I don't think anyone is objecting to resolving this, it's more a
> > > matter of *how* we can resolve it.
> >
> > currently I am see four crazy/stupid paths forward, each with their own
> > pain points.

...

> > 4. caching a reference in the audit_context as paul has suggested.
>
> I don't like this idea, but I'm struggling to come up with something
> less awful.  Below is a quick, untested patch to describe the concept
> with code.  It is worth noting that we don't take a mm_struct
> reference in the io_uring entry point because I'm not sure filtering
> on the executable file makes much sense there given the async nature
> of io_uring, however I'm open to comments here (as well as pretty much
> everything else in this pseudo-patch).

Looking at this a bit more, I'm now wondering if there is a fifth
option: call mmget() directly and skip the task_lock().

Take a look at the move_pages(2) code path:

 SYSCALL_DEFINE6(move_pages, ...)
   -> kernel_move_pages(...)
     -> find_mm_struct(...)
       -> mmget(...)

In find_mm_struct(), if the task being manipulated is *not* the
current task then get_task_mm() is called, which takes task_lock().
However, if the task being manipulated *is* the current task then the
task_lock() can be avoided and a direct call to get_mm() is used;
get_mm() does a simple atomic_inc() without any additional locking.

What do you think of this approach (untested, copy-n-pasted patch):

diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 65075f1e4ac8..ffd17ad97324 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -526,8 +526,19 @@ int audit_exe_compare(struct task_struct *tsk, struct audit
_fsnotify_mark *mark)
       struct file *exe_file;
       unsigned long ino;
       dev_t dev;
+       struct mm_struct *mm;

-       exe_file = get_task_exe_file(tsk);
+       /* almost always (always?) comparing @current, but handle both cases */
+       if (likely(tsk == current)) {
+               mmget(current->mm);
+               mm = current->mm;
+       } else {
+               mm = get_task_mm(tsk);
+               if (!mm)
+                       return 0;
+       }
+       exe_file = get_mm_exe_file(mm);
+       mmput(mm);
       if (!exe_file)
               return 0;
       ino = file_inode(exe_file)->i_ino;

--
paul-moore.com

Reply via email to