* [PATCH V4] audit: add tty field to LOGIN event
@ 2016-04-21 18:14 Richard Guy Briggs
2016-04-22 1:29 ` Paul Moore
2016-04-22 17:16 ` Peter Hurley
0 siblings, 2 replies; 13+ messages in thread
From: Richard Guy Briggs @ 2016-04-21 18:14 UTC (permalink / raw)
To: linux-audit, linux-kernel
Cc: Richard Guy Briggs, peter, sgrubb, pmoore, eparis
The tty field was missing from AUDIT_LOGIN events.
Refactor code to create a new function audit_get_tty(), using it to
replace the call in audit_log_task_info() and to add it to
audit_log_set_loginuid(). Lock and bump the kref to protect it, adding
audit_put_tty() alias to decrement it.
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
V4: Add missing prototype for audit_put_tty() when audit syscall is not
enabled (MIPS).
V3: Introduce audit_put_tty() alias to decrement kref.
V2: Use kref to protect tty signal struct while in use.
---
include/linux/audit.h | 24 ++++++++++++++++++++++++
kernel/audit.c | 18 +++++-------------
kernel/auditsc.c | 8 ++++++--
3 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index b40ed5d..32cdafb 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -26,6 +26,7 @@
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <uapi/linux/audit.h>
+#include <linux/tty.h>
#define AUDIT_INO_UNSET ((unsigned long)-1)
#define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
return tsk->sessionid;
}
+static inline struct tty_struct *audit_get_tty(struct task_struct *tsk)
+{
+ struct tty_struct *tty = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ if (tsk->signal)
+ tty = tty_kref_get(tsk->signal->tty);
+ spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ return tty;
+}
+
+static inline void audit_put_tty(struct tty_struct *tty)
+{
+ tty_kref_put(tty);
+}
+
extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode);
extern void __audit_bprm(struct linux_binprm *bprm);
@@ -500,6 +518,12 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
{
return -1;
}
+static inline struct tty_struct *audit_get_tty(struct task_struct *tsk)
+{
+ return NULL;
+}
+static inline void audit_put_tty(struct tty_struct *tty)
+{ }
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{ }
static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid,
diff --git a/kernel/audit.c b/kernel/audit.c
index 3a3e5de..7edd776 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -64,7 +64,6 @@
#include <linux/security.h>
#endif
#include <linux/freezer.h>
-#include <linux/tty.h>
#include <linux/pid_namespace.h>
#include <net/netns/generic.h>
@@ -1873,21 +1872,14 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
{
const struct cred *cred;
char comm[sizeof(tsk->comm)];
- char *tty;
+ struct tty_struct *tty;
if (!ab)
return;
/* tsk == current */
cred = current_cred();
-
- spin_lock_irq(&tsk->sighand->siglock);
- if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
- tty = tsk->signal->tty->name;
- else
- tty = "(none)";
- spin_unlock_irq(&tsk->sighand->siglock);
-
+ tty = audit_get_tty(tsk);
audit_log_format(ab,
" ppid=%d pid=%d auid=%u uid=%u gid=%u"
" euid=%u suid=%u fsuid=%u"
@@ -1903,11 +1895,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
from_kgid(&init_user_ns, cred->egid),
from_kgid(&init_user_ns, cred->sgid),
from_kgid(&init_user_ns, cred->fsgid),
- tty, audit_get_sessionid(tsk));
-
+ tty ? tty_name(tty) : "(none)",
+ audit_get_sessionid(tsk));
+ audit_put_tty(tty);
audit_log_format(ab, " comm=");
audit_log_untrustedstring(ab, get_task_comm(comm, tsk));
-
audit_log_d_path_exe(ab, tsk->mm);
audit_log_task_context(ab);
}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 195ffae..71e14d8 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid,
{
struct audit_buffer *ab;
uid_t uid, oldloginuid, loginuid;
+ struct tty_struct *tty;
if (!audit_enabled)
return;
@@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid,
uid = from_kuid(&init_user_ns, task_uid(current));
oldloginuid = from_kuid(&init_user_ns, koldloginuid);
loginuid = from_kuid(&init_user_ns, kloginuid),
+ tty = audit_get_tty(current);
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
if (!ab)
return;
audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid);
audit_log_task_context(ab);
- audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d",
- oldloginuid, loginuid, oldsessionid, sessionid, !rc);
+ audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d",
+ oldloginuid, loginuid, tty ? tty_name(tty) : "(none)",
+ oldsessionid, sessionid, !rc);
+ audit_put_tty(tty);
audit_log_end(ab);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-21 18:14 [PATCH V4] audit: add tty field to LOGIN event Richard Guy Briggs @ 2016-04-22 1:29 ` Paul Moore 2016-04-22 3:50 ` Richard Guy Briggs 2016-04-22 13:13 ` Steve Grubb 2016-04-22 17:16 ` Peter Hurley 1 sibling, 2 replies; 13+ messages in thread From: Paul Moore @ 2016-04-22 1:29 UTC (permalink / raw) To: Richard Guy Briggs; +Cc: linux-audit, linux-kernel, peter On Thu, Apr 21, 2016 at 2:14 PM, Richard Guy Briggs <rgb@redhat.com> wrote: > The tty field was missing from AUDIT_LOGIN events. > > Refactor code to create a new function audit_get_tty(), using it to > replace the call in audit_log_task_info() and to add it to > audit_log_set_loginuid(). Lock and bump the kref to protect it, adding > audit_put_tty() alias to decrement it. > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com> > --- > > V4: Add missing prototype for audit_put_tty() when audit syscall is not > enabled (MIPS). > > V3: Introduce audit_put_tty() alias to decrement kref. > > V2: Use kref to protect tty signal struct while in use. > > --- > > include/linux/audit.h | 24 ++++++++++++++++++++++++ > kernel/audit.c | 18 +++++------------- > kernel/auditsc.c | 8 ++++++-- > 3 files changed, 35 insertions(+), 15 deletions(-) > > diff --git a/include/linux/audit.h b/include/linux/audit.h > index b40ed5d..32cdafb 100644 > --- a/include/linux/audit.h > +++ b/include/linux/audit.h > @@ -26,6 +26,7 @@ > #include <linux/sched.h> > #include <linux/ptrace.h> > #include <uapi/linux/audit.h> > +#include <linux/tty.h> > > #define AUDIT_INO_UNSET ((unsigned long)-1) > #define AUDIT_DEV_UNSET ((dev_t)-1) > @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > return tsk->sessionid; > } > > +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) > +{ > + struct tty_struct *tty = NULL; > + unsigned long flags; > + > + spin_lock_irqsave(&tsk->sighand->siglock, flags); > + if (tsk->signal) > + tty = tty_kref_get(tsk->signal->tty); > + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); > + return tty; > +} > + > +static inline void audit_put_tty(struct tty_struct *tty) > +{ > + tty_kref_put(tty); > +} I'm generally not a big fan of defining functions as inlines in header files, with the general exception of dummy functions that will get compiled out. Although I guess there might be some performance argument to be made wrt audit_log_task_info(). I guess I'm fine with this, but what was the idea behind the static inlines in audit.h? Performance, or something else? > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > index 195ffae..71e14d8 100644 > --- a/kernel/auditsc.c > +++ b/kernel/auditsc.c > @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > { > struct audit_buffer *ab; > uid_t uid, oldloginuid, loginuid; > + struct tty_struct *tty; > > if (!audit_enabled) > return; > @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > uid = from_kuid(&init_user_ns, task_uid(current)); > oldloginuid = from_kuid(&init_user_ns, koldloginuid); > loginuid = from_kuid(&init_user_ns, kloginuid), > + tty = audit_get_tty(current); > > ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); > if (!ab) > return; > audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); > audit_log_task_context(ab); > - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", > - oldloginuid, loginuid, oldsessionid, sessionid, !rc); > + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", > + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", > + oldsessionid, sessionid, !rc); > + audit_put_tty(tty); > audit_log_end(ab); > } Because we are still using the crappy fixed string format for kernel<->userspace communication, this patch will likely "break the world" ... let's check with Steve but I believe the way to handle this is to add the tty information to the end of the record. -- paul moore www.paul-moore.com ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-22 1:29 ` Paul Moore @ 2016-04-22 3:50 ` Richard Guy Briggs 2016-04-22 15:02 ` Paul Moore 2016-04-22 13:13 ` Steve Grubb 1 sibling, 1 reply; 13+ messages in thread From: Richard Guy Briggs @ 2016-04-22 3:50 UTC (permalink / raw) To: Paul Moore; +Cc: linux-audit, linux-kernel, peter On 16/04/21, Paul Moore wrote: > On Thu, Apr 21, 2016 at 2:14 PM, Richard Guy Briggs <rgb@redhat.com> wrote: > > The tty field was missing from AUDIT_LOGIN events. > > > > Refactor code to create a new function audit_get_tty(), using it to > > replace the call in audit_log_task_info() and to add it to > > audit_log_set_loginuid(). Lock and bump the kref to protect it, adding > > audit_put_tty() alias to decrement it. > > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com> > > --- > > > > V4: Add missing prototype for audit_put_tty() when audit syscall is not > > enabled (MIPS). > > > > V3: Introduce audit_put_tty() alias to decrement kref. > > > > V2: Use kref to protect tty signal struct while in use. > > > > --- > > > > include/linux/audit.h | 24 ++++++++++++++++++++++++ > > kernel/audit.c | 18 +++++------------- > > kernel/auditsc.c | 8 ++++++-- > > 3 files changed, 35 insertions(+), 15 deletions(-) > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h > > index b40ed5d..32cdafb 100644 > > --- a/include/linux/audit.h > > +++ b/include/linux/audit.h > > @@ -26,6 +26,7 @@ > > #include <linux/sched.h> > > #include <linux/ptrace.h> > > #include <uapi/linux/audit.h> > > +#include <linux/tty.h> > > > > #define AUDIT_INO_UNSET ((unsigned long)-1) > > #define AUDIT_DEV_UNSET ((dev_t)-1) > > @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > > return tsk->sessionid; > > } > > > > +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) > > +{ > > + struct tty_struct *tty = NULL; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&tsk->sighand->siglock, flags); > > + if (tsk->signal) > > + tty = tty_kref_get(tsk->signal->tty); > > + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); > > + return tty; > > +} > > + > > +static inline void audit_put_tty(struct tty_struct *tty) > > +{ > > + tty_kref_put(tty); > > +} > > I'm generally not a big fan of defining functions as inlines in header > files, with the general exception of dummy functions that will get > compiled out. Although I guess there might be some performance > argument to be made wrt audit_log_task_info(). I did reflect on that initially and decided this was the least disruptive way to implement it. There are others similar around it and when I started it wasn't as involved, but now it is starting to push the limits with the kref bits... > I guess I'm fine with this, but what was the idea behind the static > inlines in audit.h? Performance, or something else? Can't say I remember... I was tempted to put it in as a define, but decided to stick with the existing style, right? :-) > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 195ffae..71e14d8 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > > { > > struct audit_buffer *ab; > > uid_t uid, oldloginuid, loginuid; > > + struct tty_struct *tty; > > > > if (!audit_enabled) > > return; > > @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > > uid = from_kuid(&init_user_ns, task_uid(current)); > > oldloginuid = from_kuid(&init_user_ns, koldloginuid); > > loginuid = from_kuid(&init_user_ns, kloginuid), > > + tty = audit_get_tty(current); > > > > ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); > > if (!ab) > > return; > > audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); > > audit_log_task_context(ab); > > - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", > > - oldloginuid, loginuid, oldsessionid, sessionid, !rc); > > + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", > > + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", > > + oldsessionid, sessionid, !rc); > > + audit_put_tty(tty); > > audit_log_end(ab); > > } > > Because we are still using the crappy fixed string format for > kernel<->userspace communication, this patch will likely "break the > world" ... let's check with Steve but I believe the way to handle this > is to add the tty information to the end of the record. Well, I did try to put that keyword consistently with where it was inserted in other messages. My understanding was that adding an extra in the middle wouldn't cause a problem because the keyword scanner looked ahead until it found the keyword it sought. This way, older scanners will just hop over this keyword it wasn't seeking. > paul moore - RGB -- Richard Guy Briggs <rgb@redhat.com> Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-22 3:50 ` Richard Guy Briggs @ 2016-04-22 15:02 ` Paul Moore 0 siblings, 0 replies; 13+ messages in thread From: Paul Moore @ 2016-04-22 15:02 UTC (permalink / raw) To: Richard Guy Briggs; +Cc: linux-audit, linux-kernel, peter On Thu, Apr 21, 2016 at 11:50 PM, Richard Guy Briggs <rgb@redhat.com> wrote: > On 16/04/21, Paul Moore wrote: >> On Thu, Apr 21, 2016 at 2:14 PM, Richard Guy Briggs <rgb@redhat.com> wrote: >> > The tty field was missing from AUDIT_LOGIN events. >> > >> > Refactor code to create a new function audit_get_tty(), using it to >> > replace the call in audit_log_task_info() and to add it to >> > audit_log_set_loginuid(). Lock and bump the kref to protect it, adding >> > audit_put_tty() alias to decrement it. >> > >> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com> >> > --- >> > >> > V4: Add missing prototype for audit_put_tty() when audit syscall is not >> > enabled (MIPS). >> > >> > V3: Introduce audit_put_tty() alias to decrement kref. >> > >> > V2: Use kref to protect tty signal struct while in use. >> > >> > --- >> > >> > include/linux/audit.h | 24 ++++++++++++++++++++++++ >> > kernel/audit.c | 18 +++++------------- >> > kernel/auditsc.c | 8 ++++++-- >> > 3 files changed, 35 insertions(+), 15 deletions(-) >> > >> > diff --git a/include/linux/audit.h b/include/linux/audit.h >> > index b40ed5d..32cdafb 100644 >> > --- a/include/linux/audit.h >> > +++ b/include/linux/audit.h >> > @@ -26,6 +26,7 @@ >> > #include <linux/sched.h> >> > #include <linux/ptrace.h> >> > #include <uapi/linux/audit.h> >> > +#include <linux/tty.h> >> > >> > #define AUDIT_INO_UNSET ((unsigned long)-1) >> > #define AUDIT_DEV_UNSET ((dev_t)-1) >> > @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) >> > return tsk->sessionid; >> > } >> > >> > +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) >> > +{ >> > + struct tty_struct *tty = NULL; >> > + unsigned long flags; >> > + >> > + spin_lock_irqsave(&tsk->sighand->siglock, flags); >> > + if (tsk->signal) >> > + tty = tty_kref_get(tsk->signal->tty); >> > + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); >> > + return tty; >> > +} >> > + >> > +static inline void audit_put_tty(struct tty_struct *tty) >> > +{ >> > + tty_kref_put(tty); >> > +} >> >> I'm generally not a big fan of defining functions as inlines in header >> files, with the general exception of dummy functions that will get >> compiled out. Although I guess there might be some performance >> argument to be made wrt audit_log_task_info(). > > I did reflect on that initially and decided this was the least > disruptive way to implement it. There are others similar around it and > when I started it wasn't as involved, but now it is starting to push the > limits with the kref bits... Yeah, that is why I mentioned it, it is sort of borderline in my opinion of what I would consider acceptable in a header file, barring some special case. >> I guess I'm fine with this, but what was the idea behind the static >> inlines in audit.h? Performance, or something else? > > Can't say I remember... I was tempted to put it in as a define, but > decided to stick with the existing style, right? :-) No, definitely not a cpp macro, we'd lose type checking and other stuff. My debate is whether or not this should life fully in the header file vs simply a prototype in the header and the definition in a C file. This is the first function where we are actually putting content into linux/audit.h, all of the existing function definitions there are dummy functions or simple wrappers for performance reasons. >> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c >> > index 195ffae..71e14d8 100644 >> > --- a/kernel/auditsc.c >> > +++ b/kernel/auditsc.c >> > @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, >> > { >> > struct audit_buffer *ab; >> > uid_t uid, oldloginuid, loginuid; >> > + struct tty_struct *tty; >> > >> > if (!audit_enabled) >> > return; >> > @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, >> > uid = from_kuid(&init_user_ns, task_uid(current)); >> > oldloginuid = from_kuid(&init_user_ns, koldloginuid); >> > loginuid = from_kuid(&init_user_ns, kloginuid), >> > + tty = audit_get_tty(current); >> > >> > ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); >> > if (!ab) >> > return; >> > audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); >> > audit_log_task_context(ab); >> > - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", >> > - oldloginuid, loginuid, oldsessionid, sessionid, !rc); >> > + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", >> > + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", >> > + oldsessionid, sessionid, !rc); >> > + audit_put_tty(tty); >> > audit_log_end(ab); >> > } >> >> Because we are still using the crappy fixed string format for >> kernel<->userspace communication, this patch will likely "break the >> world" ... let's check with Steve but I believe the way to handle this >> is to add the tty information to the end of the record. > > Well, I did try to put that keyword consistently with where it was > inserted in other messages. My understanding was that adding an extra > in the middle wouldn't cause a problem because the keyword scanner > looked ahead until it found the keyword it sought. This way, older > scanners will just hop over this keyword it wasn't seeking. I understand the idea behind consistency, and as long as it doesn't break the userspace parser(s) I agree with you. The good news is that Steve says we are in the clear wrt the new field. I'm traveling right now and I'm not sure if I'll have any time in front of a proper computer/shell to get this merged before early next week, but v4 looks reasonable to me. If you don't see this in the audit#next tree by .... let's say end of day next Tuesday ... feel free to send me a nudge. Thanks. -- paul moore www.paul-moore.com ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-22 1:29 ` Paul Moore 2016-04-22 3:50 ` Richard Guy Briggs @ 2016-04-22 13:13 ` Steve Grubb 1 sibling, 0 replies; 13+ messages in thread From: Steve Grubb @ 2016-04-22 13:13 UTC (permalink / raw) To: linux-audit; +Cc: Paul Moore, Richard Guy Briggs, linux-kernel, peter On Thursday, April 21, 2016 09:29:57 PM Paul Moore wrote: > On Thu, Apr 21, 2016 at 2:14 PM, Richard Guy Briggs <rgb@redhat.com> wrote: > > The tty field was missing from AUDIT_LOGIN events. > > > > Refactor code to create a new function audit_get_tty(), using it to > > replace the call in audit_log_task_info() and to add it to > > audit_log_set_loginuid(). Lock and bump the kref to protect it, adding > > audit_put_tty() alias to decrement it. > > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com> > > --- > > > > V4: Add missing prototype for audit_put_tty() when audit syscall is not > > > > enabled (MIPS). > > > > V3: Introduce audit_put_tty() alias to decrement kref. > > > > V2: Use kref to protect tty signal struct while in use. > > > > --- > > > > include/linux/audit.h | 24 ++++++++++++++++++++++++ > > kernel/audit.c | 18 +++++------------- > > kernel/auditsc.c | 8 ++++++-- > > 3 files changed, 35 insertions(+), 15 deletions(-) > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h > > index b40ed5d..32cdafb 100644 > > --- a/include/linux/audit.h > > +++ b/include/linux/audit.h > > @@ -26,6 +26,7 @@ > > > > #include <linux/sched.h> > > #include <linux/ptrace.h> > > #include <uapi/linux/audit.h> > > > > +#include <linux/tty.h> > > > > #define AUDIT_INO_UNSET ((unsigned long)-1) > > #define AUDIT_DEV_UNSET ((dev_t)-1) > > > > @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct > > task_struct *tsk)> > > return tsk->sessionid; > > > > } > > > > +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) > > +{ > > + struct tty_struct *tty = NULL; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&tsk->sighand->siglock, flags); > > + if (tsk->signal) > > + tty = tty_kref_get(tsk->signal->tty); > > + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); > > + return tty; > > +} > > + > > +static inline void audit_put_tty(struct tty_struct *tty) > > +{ > > + tty_kref_put(tty); > > +} > > I'm generally not a big fan of defining functions as inlines in header > files, with the general exception of dummy functions that will get > compiled out. Although I guess there might be some performance > argument to be made wrt audit_log_task_info(). > > I guess I'm fine with this, but what was the idea behind the static > inlines in audit.h? Performance, or something else? I think that is normal to prevent multiple definitions at link time. > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 195ffae..71e14d8 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t > > koldloginuid, kuid_t kloginuid,> > > { > > > > struct audit_buffer *ab; > > uid_t uid, oldloginuid, loginuid; > > > > + struct tty_struct *tty; > > > > if (!audit_enabled) > > > > return; > > > > @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t > > koldloginuid, kuid_t kloginuid,> > > uid = from_kuid(&init_user_ns, task_uid(current)); > > oldloginuid = from_kuid(&init_user_ns, koldloginuid); > > loginuid = from_kuid(&init_user_ns, kloginuid), > > > > + tty = audit_get_tty(current); > > > > ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); > > if (!ab) > > > > return; > > > > audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); > > audit_log_task_context(ab); > > > > - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u > > res=%d", - oldloginuid, loginuid, oldsessionid, > > sessionid, !rc); + audit_log_format(ab, " old-auid=%u auid=%u > > tty=%s old-ses=%u ses=%u res=%d", + oldloginuid, > > loginuid, tty ? tty_name(tty) : "(none)", + > > oldsessionid, sessionid, !rc); > > + audit_put_tty(tty); > > > > audit_log_end(ab); > > > > } > > Because we are still using the crappy fixed string format for > kernel<->userspace communication, this patch will likely "break the > world" ... let's check with Steve but I believe the way to handle this > is to add the tty information to the end of the record. The placement is OK. Thanks for asking. -Steve ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-21 18:14 [PATCH V4] audit: add tty field to LOGIN event Richard Guy Briggs 2016-04-22 1:29 ` Paul Moore @ 2016-04-22 17:16 ` Peter Hurley 2016-04-26 22:34 ` Paul Moore 2016-04-28 1:31 ` Richard Guy Briggs 1 sibling, 2 replies; 13+ messages in thread From: Peter Hurley @ 2016-04-22 17:16 UTC (permalink / raw) To: Richard Guy Briggs, linux-audit, pmoore; +Cc: linux-kernel, sgrubb, eparis On 04/21/2016 11:14 AM, Richard Guy Briggs wrote: > The tty field was missing from AUDIT_LOGIN events. > > Refactor code to create a new function audit_get_tty(), using it to > replace the call in audit_log_task_info() and to add it to > audit_log_set_loginuid(). Lock and bump the kref to protect it, adding > audit_put_tty() alias to decrement it. > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com> > --- > > V4: Add missing prototype for audit_put_tty() when audit syscall is not > enabled (MIPS). > > V3: Introduce audit_put_tty() alias to decrement kref. > > V2: Use kref to protect tty signal struct while in use. > > --- > > include/linux/audit.h | 24 ++++++++++++++++++++++++ > kernel/audit.c | 18 +++++------------- > kernel/auditsc.c | 8 ++++++-- > 3 files changed, 35 insertions(+), 15 deletions(-) > > diff --git a/include/linux/audit.h b/include/linux/audit.h > index b40ed5d..32cdafb 100644 > --- a/include/linux/audit.h > +++ b/include/linux/audit.h > @@ -26,6 +26,7 @@ > #include <linux/sched.h> > #include <linux/ptrace.h> > #include <uapi/linux/audit.h> > +#include <linux/tty.h> > > #define AUDIT_INO_UNSET ((unsigned long)-1) > #define AUDIT_DEV_UNSET ((dev_t)-1) > @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > return tsk->sessionid; > } > > +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) > +{ > + struct tty_struct *tty = NULL; > + unsigned long flags; > + > + spin_lock_irqsave(&tsk->sighand->siglock, flags); > + if (tsk->signal) > + tty = tty_kref_get(tsk->signal->tty); > + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); Not that I'm objecting because I get that you're just refactoring existing code, but I thought I'd point out some stuff. 1. There's no need to check if signal_struct is NULL (ie. tsk->signal) because if it is, this will blow up trying to dereference the sighand_struct (ie tsk->sighand). 2. The existing usage is always tsk==current 3. If the idea is to make this invulnerable to tsk being gone, then the usage is unsafe anyway. So ultimately (but not necessarily for this patch) I'd prefer that either a. audit use existing tty api instead of open-coding, or b. add any tty api functions required. Regards, Peter Hurley > + return tty; > +} > + > +static inline void audit_put_tty(struct tty_struct *tty) > +{ > + tty_kref_put(tty); > +} > + > extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); > extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); > extern void __audit_bprm(struct linux_binprm *bprm); > @@ -500,6 +518,12 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > { > return -1; > } > +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) > +{ > + return NULL; > +} > +static inline void audit_put_tty(struct tty_struct *tty) > +{ } > static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) > { } > static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, > diff --git a/kernel/audit.c b/kernel/audit.c > index 3a3e5de..7edd776 100644 > --- a/kernel/audit.c > +++ b/kernel/audit.c > @@ -64,7 +64,6 @@ > #include <linux/security.h> > #endif > #include <linux/freezer.h> > -#include <linux/tty.h> > #include <linux/pid_namespace.h> > #include <net/netns/generic.h> > > @@ -1873,21 +1872,14 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) > { > const struct cred *cred; > char comm[sizeof(tsk->comm)]; > - char *tty; > + struct tty_struct *tty; > > if (!ab) > return; > > /* tsk == current */ > cred = current_cred(); > - > - spin_lock_irq(&tsk->sighand->siglock); > - if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) > - tty = tsk->signal->tty->name; > - else > - tty = "(none)"; > - spin_unlock_irq(&tsk->sighand->siglock); > - > + tty = audit_get_tty(tsk); > audit_log_format(ab, > " ppid=%d pid=%d auid=%u uid=%u gid=%u" > " euid=%u suid=%u fsuid=%u" > @@ -1903,11 +1895,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) > from_kgid(&init_user_ns, cred->egid), > from_kgid(&init_user_ns, cred->sgid), > from_kgid(&init_user_ns, cred->fsgid), > - tty, audit_get_sessionid(tsk)); > - > + tty ? tty_name(tty) : "(none)", > + audit_get_sessionid(tsk)); > + audit_put_tty(tty); > audit_log_format(ab, " comm="); > audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); > - > audit_log_d_path_exe(ab, tsk->mm); > audit_log_task_context(ab); > } > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > index 195ffae..71e14d8 100644 > --- a/kernel/auditsc.c > +++ b/kernel/auditsc.c > @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > { > struct audit_buffer *ab; > uid_t uid, oldloginuid, loginuid; > + struct tty_struct *tty; > > if (!audit_enabled) > return; > @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > uid = from_kuid(&init_user_ns, task_uid(current)); > oldloginuid = from_kuid(&init_user_ns, koldloginuid); > loginuid = from_kuid(&init_user_ns, kloginuid), > + tty = audit_get_tty(current); > > ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); > if (!ab) > return; > audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); > audit_log_task_context(ab); > - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", > - oldloginuid, loginuid, oldsessionid, sessionid, !rc); > + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", > + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", > + oldsessionid, sessionid, !rc); > + audit_put_tty(tty); > audit_log_end(ab); > } > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-22 17:16 ` Peter Hurley @ 2016-04-26 22:34 ` Paul Moore 2016-04-27 0:57 ` Peter Hurley 2016-04-28 1:31 ` Richard Guy Briggs 1 sibling, 1 reply; 13+ messages in thread From: Paul Moore @ 2016-04-26 22:34 UTC (permalink / raw) To: Peter Hurley, Richard Guy Briggs; +Cc: linux-audit, Paul Moore, linux-kernel On Fri, Apr 22, 2016 at 1:16 PM, Peter Hurley <peter@hurleysoftware.com> wrote: > On 04/21/2016 11:14 AM, Richard Guy Briggs wrote: >> diff --git a/include/linux/audit.h b/include/linux/audit.h >> index b40ed5d..32cdafb 100644 >> --- a/include/linux/audit.h >> +++ b/include/linux/audit.h >> @@ -26,6 +26,7 @@ >> #include <linux/sched.h> >> #include <linux/ptrace.h> >> #include <uapi/linux/audit.h> >> +#include <linux/tty.h> >> >> #define AUDIT_INO_UNSET ((unsigned long)-1) >> #define AUDIT_DEV_UNSET ((dev_t)-1) >> @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) >> return tsk->sessionid; >> } >> >> +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) >> +{ >> + struct tty_struct *tty = NULL; >> + unsigned long flags; >> + >> + spin_lock_irqsave(&tsk->sighand->siglock, flags); >> + if (tsk->signal) >> + tty = tty_kref_get(tsk->signal->tty); >> + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); I just merged Richard's patch, if nothing else it is better than it was. However, I would like to talk about improving things, see below. > Not that I'm objecting because I get that you're just refactoring > existing code, but I thought I'd point out some stuff. > > 1. There's no need to check if signal_struct is NULL (ie. tsk->signal) > because if it is, this will blow up trying to dereference the > sighand_struct (ie tsk->sighand). > > 2. The existing usage is always tsk==current Yep, there is only one caller I found that even works on task_structs other than current (see audit_log_exit() via audit_free()), although even then when it ends up calling into audit_log_task_info() tsk should always be current. I've got a patch compiling now to get rid of passing around current as a a task_struct argument, assuming nothing blows up in testing I'll post/merge it. > 3. If the idea is to make this invulnerable to tsk being gone, then > the usage is unsafe anyway. I don't think that is our concern here. > So ultimately (but not necessarily for this patch) I'd prefer that either > a. audit use existing tty api instead of open-coding, or > b. add any tty api functions required. I'm open to suggestions, care to elaborate on either option? Feel free to elaborate by patch too ;) -- paul moore www.paul-moore.com ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-26 22:34 ` Paul Moore @ 2016-04-27 0:57 ` Peter Hurley 0 siblings, 0 replies; 13+ messages in thread From: Peter Hurley @ 2016-04-27 0:57 UTC (permalink / raw) To: Paul Moore, Richard Guy Briggs; +Cc: linux-audit, Paul Moore, linux-kernel On 04/26/2016 03:34 PM, Paul Moore wrote: > On Fri, Apr 22, 2016 at 1:16 PM, Peter Hurley <peter@hurleysoftware.com> wrote: >> On 04/21/2016 11:14 AM, Richard Guy Briggs wrote: >>> diff --git a/include/linux/audit.h b/include/linux/audit.h >>> index b40ed5d..32cdafb 100644 >>> --- a/include/linux/audit.h >>> +++ b/include/linux/audit.h >>> @@ -26,6 +26,7 @@ >>> #include <linux/sched.h> >>> #include <linux/ptrace.h> >>> #include <uapi/linux/audit.h> >>> +#include <linux/tty.h> >>> >>> #define AUDIT_INO_UNSET ((unsigned long)-1) >>> #define AUDIT_DEV_UNSET ((dev_t)-1) >>> @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) >>> return tsk->sessionid; >>> } >>> >>> +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) >>> +{ >>> + struct tty_struct *tty = NULL; >>> + unsigned long flags; >>> + >>> + spin_lock_irqsave(&tsk->sighand->siglock, flags); >>> + if (tsk->signal) >>> + tty = tty_kref_get(tsk->signal->tty); >>> + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); > > I just merged Richard's patch, if nothing else it is better than it > was. However, I would like to talk about improving things, see below. > >> Not that I'm objecting because I get that you're just refactoring >> existing code, but I thought I'd point out some stuff. >> >> 1. There's no need to check if signal_struct is NULL (ie. tsk->signal) >> because if it is, this will blow up trying to dereference the >> sighand_struct (ie tsk->sighand). >> >> 2. The existing usage is always tsk==current > > Yep, there is only one caller I found that even works on task_structs > other than current (see audit_log_exit() via audit_free()), although > even then when it ends up calling into audit_log_task_info() tsk > should always be current. > > I've got a patch compiling now to get rid of passing around current as > a a task_struct argument, assuming nothing blows up in testing I'll > post/merge it. > >> 3. If the idea is to make this invulnerable to tsk being gone, then >> the usage is unsafe anyway. > > I don't think that is our concern here. > >> So ultimately (but not necessarily for this patch) I'd prefer that either >> a. audit use existing tty api instead of open-coding, or >> b. add any tty api functions required. > > I'm open to suggestions, care to elaborate on either option? So b) is only necessary if the answer to 3) was yes or if tsk != current. Otherwise, the new audit_get_tty() is equivalent to get_current_tty() which is the exported tty core interface for the identical operation. I was only suggesting b) if get_current_tty() wasn't going to be sufficient. > Feel free to elaborate by patch too ;) I can do that. Regards, Peter Hurley ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-22 17:16 ` Peter Hurley 2016-04-26 22:34 ` Paul Moore @ 2016-04-28 1:31 ` Richard Guy Briggs 2016-04-28 3:05 ` Peter Hurley 2016-04-28 20:07 ` Paul Moore 1 sibling, 2 replies; 13+ messages in thread From: Richard Guy Briggs @ 2016-04-28 1:31 UTC (permalink / raw) To: Peter Hurley; +Cc: linux-audit, pmoore, linux-kernel, sgrubb, eparis On 16/04/22, Peter Hurley wrote: > On 04/21/2016 11:14 AM, Richard Guy Briggs wrote: > > The tty field was missing from AUDIT_LOGIN events. > > > > Refactor code to create a new function audit_get_tty(), using it to > > replace the call in audit_log_task_info() and to add it to > > audit_log_set_loginuid(). Lock and bump the kref to protect it, adding > > audit_put_tty() alias to decrement it. > > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com> > > --- > > > > V4: Add missing prototype for audit_put_tty() when audit syscall is not > > enabled (MIPS). > > > > V3: Introduce audit_put_tty() alias to decrement kref. > > > > V2: Use kref to protect tty signal struct while in use. > > > > --- > > > > include/linux/audit.h | 24 ++++++++++++++++++++++++ > > kernel/audit.c | 18 +++++------------- > > kernel/auditsc.c | 8 ++++++-- > > 3 files changed, 35 insertions(+), 15 deletions(-) > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h > > index b40ed5d..32cdafb 100644 > > --- a/include/linux/audit.h > > +++ b/include/linux/audit.h > > @@ -26,6 +26,7 @@ > > #include <linux/sched.h> > > #include <linux/ptrace.h> > > #include <uapi/linux/audit.h> > > +#include <linux/tty.h> > > > > #define AUDIT_INO_UNSET ((unsigned long)-1) > > #define AUDIT_DEV_UNSET ((dev_t)-1) > > @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > > return tsk->sessionid; > > } > > > > +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) > > +{ > > + struct tty_struct *tty = NULL; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&tsk->sighand->siglock, flags); > > + if (tsk->signal) > > + tty = tty_kref_get(tsk->signal->tty); > > + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); > > > Not that I'm objecting because I get that you're just refactoring > existing code, but I thought I'd point out some stuff. > > 1. There's no need to check if signal_struct is NULL (ie. tsk->signal) > because if it is, this will blow up trying to dereference the > sighand_struct (ie tsk->sighand). Ok. This logic goes back 10 years and one month less two days. (45d9bb0e) > 2. The existing usage is always tsk==current My understanding is that when it is called via: copy_process() audit_free() __audit_free() audit_log_exit() audit_log_task_info() then tsk != current. This appears to be the only case which appears to force lugging around tsk. This is noted in that commit referenced above. > 3. If the idea is to make this invulnerable to tsk being gone, then > the usage is unsafe anyway. > > > So ultimately (but not necessarily for this patch) I'd prefer that either > a. audit use existing tty api instead of open-coding, or > b. add any tty api functions required. This latter option did cross my mind... > Peter Hurley > > > + return tty; > > +} > > + > > +static inline void audit_put_tty(struct tty_struct *tty) > > +{ > > + tty_kref_put(tty); > > +} > > + > > extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); > > extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); > > extern void __audit_bprm(struct linux_binprm *bprm); > > @@ -500,6 +518,12 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > > { > > return -1; > > } > > +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) > > +{ > > + return NULL; > > +} > > +static inline void audit_put_tty(struct tty_struct *tty) > > +{ } > > static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) > > { } > > static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, > > diff --git a/kernel/audit.c b/kernel/audit.c > > index 3a3e5de..7edd776 100644 > > --- a/kernel/audit.c > > +++ b/kernel/audit.c > > @@ -64,7 +64,6 @@ > > #include <linux/security.h> > > #endif > > #include <linux/freezer.h> > > -#include <linux/tty.h> > > #include <linux/pid_namespace.h> > > #include <net/netns/generic.h> > > > > @@ -1873,21 +1872,14 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) > > { > > const struct cred *cred; > > char comm[sizeof(tsk->comm)]; > > - char *tty; > > + struct tty_struct *tty; > > > > if (!ab) > > return; > > > > /* tsk == current */ > > cred = current_cred(); > > - > > - spin_lock_irq(&tsk->sighand->siglock); > > - if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) > > - tty = tsk->signal->tty->name; > > - else > > - tty = "(none)"; > > - spin_unlock_irq(&tsk->sighand->siglock); > > - > > + tty = audit_get_tty(tsk); > > audit_log_format(ab, > > " ppid=%d pid=%d auid=%u uid=%u gid=%u" > > " euid=%u suid=%u fsuid=%u" > > @@ -1903,11 +1895,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) > > from_kgid(&init_user_ns, cred->egid), > > from_kgid(&init_user_ns, cred->sgid), > > from_kgid(&init_user_ns, cred->fsgid), > > - tty, audit_get_sessionid(tsk)); > > - > > + tty ? tty_name(tty) : "(none)", > > + audit_get_sessionid(tsk)); > > + audit_put_tty(tty); > > audit_log_format(ab, " comm="); > > audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); > > - > > audit_log_d_path_exe(ab, tsk->mm); > > audit_log_task_context(ab); > > } > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 195ffae..71e14d8 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > > { > > struct audit_buffer *ab; > > uid_t uid, oldloginuid, loginuid; > > + struct tty_struct *tty; > > > > if (!audit_enabled) > > return; > > @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > > uid = from_kuid(&init_user_ns, task_uid(current)); > > oldloginuid = from_kuid(&init_user_ns, koldloginuid); > > loginuid = from_kuid(&init_user_ns, kloginuid), > > + tty = audit_get_tty(current); > > > > ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); > > if (!ab) > > return; > > audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); > > audit_log_task_context(ab); > > - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", > > - oldloginuid, loginuid, oldsessionid, sessionid, !rc); > > + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", > > + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", > > + oldsessionid, sessionid, !rc); > > + audit_put_tty(tty); > > audit_log_end(ab); > > } > > > > > - RGB -- Richard Guy Briggs <rgb@redhat.com> Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-28 1:31 ` Richard Guy Briggs @ 2016-04-28 3:05 ` Peter Hurley 2016-04-28 19:28 ` Richard Guy Briggs 2016-04-28 20:07 ` Paul Moore 1 sibling, 1 reply; 13+ messages in thread From: Peter Hurley @ 2016-04-28 3:05 UTC (permalink / raw) To: Richard Guy Briggs; +Cc: linux-audit, pmoore, linux-kernel, sgrubb, eparis On 04/27/2016 06:31 PM, Richard Guy Briggs wrote: > On 16/04/22, Peter Hurley wrote: >> On 04/21/2016 11:14 AM, Richard Guy Briggs wrote: >>> The tty field was missing from AUDIT_LOGIN events. >>> >>> Refactor code to create a new function audit_get_tty(), using it to >>> replace the call in audit_log_task_info() and to add it to >>> audit_log_set_loginuid(). Lock and bump the kref to protect it, adding >>> audit_put_tty() alias to decrement it. >>> >>> Signed-off-by: Richard Guy Briggs <rgb@redhat.com> >>> --- >>> >>> V4: Add missing prototype for audit_put_tty() when audit syscall is not >>> enabled (MIPS). >>> >>> V3: Introduce audit_put_tty() alias to decrement kref. >>> >>> V2: Use kref to protect tty signal struct while in use. >>> >>> --- >>> >>> include/linux/audit.h | 24 ++++++++++++++++++++++++ >>> kernel/audit.c | 18 +++++------------- >>> kernel/auditsc.c | 8 ++++++-- >>> 3 files changed, 35 insertions(+), 15 deletions(-) >>> >>> diff --git a/include/linux/audit.h b/include/linux/audit.h >>> index b40ed5d..32cdafb 100644 >>> --- a/include/linux/audit.h >>> +++ b/include/linux/audit.h >>> @@ -26,6 +26,7 @@ >>> #include <linux/sched.h> >>> #include <linux/ptrace.h> >>> #include <uapi/linux/audit.h> >>> +#include <linux/tty.h> >>> >>> #define AUDIT_INO_UNSET ((unsigned long)-1) >>> #define AUDIT_DEV_UNSET ((dev_t)-1) >>> @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) >>> return tsk->sessionid; >>> } >>> >>> +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) >>> +{ >>> + struct tty_struct *tty = NULL; >>> + unsigned long flags; >>> + >>> + spin_lock_irqsave(&tsk->sighand->siglock, flags); >>> + if (tsk->signal) >>> + tty = tty_kref_get(tsk->signal->tty); >>> + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); >> >> >> Not that I'm objecting because I get that you're just refactoring >> existing code, but I thought I'd point out some stuff. >> >> 1. There's no need to check if signal_struct is NULL (ie. tsk->signal) >> because if it is, this will blow up trying to dereference the >> sighand_struct (ie tsk->sighand). > > Ok. This logic goes back 10 years and one month less two days. (45d9bb0e) > >> 2. The existing usage is always tsk==current > > My understanding is that when it is called via: > > copy_process() > audit_free() > __audit_free() > audit_log_exit() > audit_log_task_info() > > then tsk != current. While it's true that tsk != current here, everything relevant to tty in task_struct is the same because the nascent task is not even half-done. So tsk->sighand == current->sighand, tsk->signal == current->signal etc. If you're uncomfortable with pass-through execution like that, then the simple solution is: struct tty_struct *tty = NULL; /* tsk != current when copy_process() failed */ if (tsk == current) tty = get_current_tty(); because tty_kref_put(tty) accepts NULL tty and (obviously) so does tty_name(tty). Regards, Peter Hurley > This appears to be the only case which appears to > force lugging around tsk. This is noted in that commit referenced > above. > >> 3. If the idea is to make this invulnerable to tsk being gone, then >> the usage is unsafe anyway. >> >> >> So ultimately (but not necessarily for this patch) I'd prefer that either >> a. audit use existing tty api instead of open-coding, or >> b. add any tty api functions required. > > This latter option did cross my mind... > >> Peter Hurley >> >>> + return tty; >>> +} >>> + >>> +static inline void audit_put_tty(struct tty_struct *tty) >>> +{ >>> + tty_kref_put(tty); >>> +} >>> + >>> extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); >>> extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); >>> extern void __audit_bprm(struct linux_binprm *bprm); >>> @@ -500,6 +518,12 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) >>> { >>> return -1; >>> } >>> +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) >>> +{ >>> + return NULL; >>> +} >>> +static inline void audit_put_tty(struct tty_struct *tty) >>> +{ } >>> static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) >>> { } >>> static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, >>> diff --git a/kernel/audit.c b/kernel/audit.c >>> index 3a3e5de..7edd776 100644 >>> --- a/kernel/audit.c >>> +++ b/kernel/audit.c >>> @@ -64,7 +64,6 @@ >>> #include <linux/security.h> >>> #endif >>> #include <linux/freezer.h> >>> -#include <linux/tty.h> >>> #include <linux/pid_namespace.h> >>> #include <net/netns/generic.h> >>> >>> @@ -1873,21 +1872,14 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) >>> { >>> const struct cred *cred; >>> char comm[sizeof(tsk->comm)]; >>> - char *tty; >>> + struct tty_struct *tty; >>> >>> if (!ab) >>> return; >>> >>> /* tsk == current */ >>> cred = current_cred(); >>> - >>> - spin_lock_irq(&tsk->sighand->siglock); >>> - if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) >>> - tty = tsk->signal->tty->name; >>> - else >>> - tty = "(none)"; >>> - spin_unlock_irq(&tsk->sighand->siglock); >>> - >>> + tty = audit_get_tty(tsk); >>> audit_log_format(ab, >>> " ppid=%d pid=%d auid=%u uid=%u gid=%u" >>> " euid=%u suid=%u fsuid=%u" >>> @@ -1903,11 +1895,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) >>> from_kgid(&init_user_ns, cred->egid), >>> from_kgid(&init_user_ns, cred->sgid), >>> from_kgid(&init_user_ns, cred->fsgid), >>> - tty, audit_get_sessionid(tsk)); >>> - >>> + tty ? tty_name(tty) : "(none)", >>> + audit_get_sessionid(tsk)); >>> + audit_put_tty(tty); >>> audit_log_format(ab, " comm="); >>> audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); >>> - >>> audit_log_d_path_exe(ab, tsk->mm); >>> audit_log_task_context(ab); >>> } >>> diff --git a/kernel/auditsc.c b/kernel/auditsc.c >>> index 195ffae..71e14d8 100644 >>> --- a/kernel/auditsc.c >>> +++ b/kernel/auditsc.c >>> @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, >>> { >>> struct audit_buffer *ab; >>> uid_t uid, oldloginuid, loginuid; >>> + struct tty_struct *tty; >>> >>> if (!audit_enabled) >>> return; >>> @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, >>> uid = from_kuid(&init_user_ns, task_uid(current)); >>> oldloginuid = from_kuid(&init_user_ns, koldloginuid); >>> loginuid = from_kuid(&init_user_ns, kloginuid), >>> + tty = audit_get_tty(current); >>> >>> ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); >>> if (!ab) >>> return; >>> audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); >>> audit_log_task_context(ab); >>> - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", >>> - oldloginuid, loginuid, oldsessionid, sessionid, !rc); >>> + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", >>> + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", >>> + oldsessionid, sessionid, !rc); >>> + audit_put_tty(tty); >>> audit_log_end(ab); >>> } >>> >>> >> > > - RGB > > -- > Richard Guy Briggs <rgb@redhat.com> > Kernel Security Engineering, Base Operating Systems, Red Hat > Remote, Ottawa, Canada > Voice: +1.647.777.2635, Internal: (81) 32635 > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-28 3:05 ` Peter Hurley @ 2016-04-28 19:28 ` Richard Guy Briggs 2016-04-28 19:32 ` Peter Hurley 0 siblings, 1 reply; 13+ messages in thread From: Richard Guy Briggs @ 2016-04-28 19:28 UTC (permalink / raw) To: Peter Hurley; +Cc: linux-audit, pmoore, linux-kernel, sgrubb, eparis On 16/04/27, Peter Hurley wrote: > On 04/27/2016 06:31 PM, Richard Guy Briggs wrote: > > On 16/04/22, Peter Hurley wrote: > >> On 04/21/2016 11:14 AM, Richard Guy Briggs wrote: > >>> The tty field was missing from AUDIT_LOGIN events. > >>> > >>> Refactor code to create a new function audit_get_tty(), using it to > >>> replace the call in audit_log_task_info() and to add it to > >>> audit_log_set_loginuid(). Lock and bump the kref to protect it, adding > >>> audit_put_tty() alias to decrement it. > >>> > >>> Signed-off-by: Richard Guy Briggs <rgb@redhat.com> > >>> --- > >>> > >>> V4: Add missing prototype for audit_put_tty() when audit syscall is not > >>> enabled (MIPS). > >>> > >>> V3: Introduce audit_put_tty() alias to decrement kref. > >>> > >>> V2: Use kref to protect tty signal struct while in use. > >>> > >>> --- > >>> > >>> include/linux/audit.h | 24 ++++++++++++++++++++++++ > >>> kernel/audit.c | 18 +++++------------- > >>> kernel/auditsc.c | 8 ++++++-- > >>> 3 files changed, 35 insertions(+), 15 deletions(-) > >>> > >>> diff --git a/include/linux/audit.h b/include/linux/audit.h > >>> index b40ed5d..32cdafb 100644 > >>> --- a/include/linux/audit.h > >>> +++ b/include/linux/audit.h > >>> @@ -26,6 +26,7 @@ > >>> #include <linux/sched.h> > >>> #include <linux/ptrace.h> > >>> #include <uapi/linux/audit.h> > >>> +#include <linux/tty.h> > >>> > >>> #define AUDIT_INO_UNSET ((unsigned long)-1) > >>> #define AUDIT_DEV_UNSET ((dev_t)-1) > >>> @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > >>> return tsk->sessionid; > >>> } > >>> > >>> +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) > >>> +{ > >>> + struct tty_struct *tty = NULL; > >>> + unsigned long flags; > >>> + > >>> + spin_lock_irqsave(&tsk->sighand->siglock, flags); > >>> + if (tsk->signal) > >>> + tty = tty_kref_get(tsk->signal->tty); > >>> + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); > >> > >> > >> Not that I'm objecting because I get that you're just refactoring > >> existing code, but I thought I'd point out some stuff. > >> > >> 1. There's no need to check if signal_struct is NULL (ie. tsk->signal) > >> because if it is, this will blow up trying to dereference the > >> sighand_struct (ie tsk->sighand). > > > > Ok. This logic goes back 10 years and one month less two days. (45d9bb0e) > > > >> 2. The existing usage is always tsk==current > > > > My understanding is that when it is called via: > > > > copy_process() > > audit_free() > > __audit_free() > > audit_log_exit() > > audit_log_task_info() > > > > then tsk != current. > > While it's true that tsk != current here, everything relevant to tty > in task_struct is the same because the nascent task is not even half-done. > So tsk->sighand == current->sighand, tsk->signal == current->signal etc. I agree this is true except in the case of !CLONE_SIGHAND, if it fails after copy_sighand() or copy_signal() then it would be null and would get freed before audit_free() is called. By the time tty gets copied from current in this case, it is past the point of failure in copy_process(). > If you're uncomfortable with pass-through execution like that, then the > simple solution is: > > struct tty_struct *tty = NULL; > > /* tsk != current when copy_process() failed */ > if (tsk == current) > tty = get_current_tty(); > > because tty_kref_put(tty) accepts NULL tty and (obviously) so does > tty_name(tty). Given the circumstances above, this appears reasonable to me at first look. > Peter Hurley > > > This appears to be the only case which appears to > > force lugging around tsk. This is noted in that commit referenced > > above. > > > >> 3. If the idea is to make this invulnerable to tsk being gone, then > >> the usage is unsafe anyway. > >> > >> > >> So ultimately (but not necessarily for this patch) I'd prefer that either > >> a. audit use existing tty api instead of open-coding, or > >> b. add any tty api functions required. > > > > This latter option did cross my mind... > > > >> Peter Hurley > >> > >>> + return tty; > >>> +} > >>> + > >>> +static inline void audit_put_tty(struct tty_struct *tty) > >>> +{ > >>> + tty_kref_put(tty); > >>> +} > >>> + > >>> extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); > >>> extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); > >>> extern void __audit_bprm(struct linux_binprm *bprm); > >>> @@ -500,6 +518,12 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > >>> { > >>> return -1; > >>> } > >>> +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) > >>> +{ > >>> + return NULL; > >>> +} > >>> +static inline void audit_put_tty(struct tty_struct *tty) > >>> +{ } > >>> static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) > >>> { } > >>> static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, > >>> diff --git a/kernel/audit.c b/kernel/audit.c > >>> index 3a3e5de..7edd776 100644 > >>> --- a/kernel/audit.c > >>> +++ b/kernel/audit.c > >>> @@ -64,7 +64,6 @@ > >>> #include <linux/security.h> > >>> #endif > >>> #include <linux/freezer.h> > >>> -#include <linux/tty.h> > >>> #include <linux/pid_namespace.h> > >>> #include <net/netns/generic.h> > >>> > >>> @@ -1873,21 +1872,14 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) > >>> { > >>> const struct cred *cred; > >>> char comm[sizeof(tsk->comm)]; > >>> - char *tty; > >>> + struct tty_struct *tty; > >>> > >>> if (!ab) > >>> return; > >>> > >>> /* tsk == current */ > >>> cred = current_cred(); > >>> - > >>> - spin_lock_irq(&tsk->sighand->siglock); > >>> - if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) > >>> - tty = tsk->signal->tty->name; > >>> - else > >>> - tty = "(none)"; > >>> - spin_unlock_irq(&tsk->sighand->siglock); > >>> - > >>> + tty = audit_get_tty(tsk); > >>> audit_log_format(ab, > >>> " ppid=%d pid=%d auid=%u uid=%u gid=%u" > >>> " euid=%u suid=%u fsuid=%u" > >>> @@ -1903,11 +1895,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) > >>> from_kgid(&init_user_ns, cred->egid), > >>> from_kgid(&init_user_ns, cred->sgid), > >>> from_kgid(&init_user_ns, cred->fsgid), > >>> - tty, audit_get_sessionid(tsk)); > >>> - > >>> + tty ? tty_name(tty) : "(none)", > >>> + audit_get_sessionid(tsk)); > >>> + audit_put_tty(tty); > >>> audit_log_format(ab, " comm="); > >>> audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); > >>> - > >>> audit_log_d_path_exe(ab, tsk->mm); > >>> audit_log_task_context(ab); > >>> } > >>> diff --git a/kernel/auditsc.c b/kernel/auditsc.c > >>> index 195ffae..71e14d8 100644 > >>> --- a/kernel/auditsc.c > >>> +++ b/kernel/auditsc.c > >>> @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > >>> { > >>> struct audit_buffer *ab; > >>> uid_t uid, oldloginuid, loginuid; > >>> + struct tty_struct *tty; > >>> > >>> if (!audit_enabled) > >>> return; > >>> @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, > >>> uid = from_kuid(&init_user_ns, task_uid(current)); > >>> oldloginuid = from_kuid(&init_user_ns, koldloginuid); > >>> loginuid = from_kuid(&init_user_ns, kloginuid), > >>> + tty = audit_get_tty(current); > >>> > >>> ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); > >>> if (!ab) > >>> return; > >>> audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); > >>> audit_log_task_context(ab); > >>> - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", > >>> - oldloginuid, loginuid, oldsessionid, sessionid, !rc); > >>> + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", > >>> + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", > >>> + oldsessionid, sessionid, !rc); > >>> + audit_put_tty(tty); > >>> audit_log_end(ab); > >>> } > >>> > >>> > >> > > > > - RGB > > > > -- > > Richard Guy Briggs <rgb@redhat.com> > > Kernel Security Engineering, Base Operating Systems, Red Hat > > Remote, Ottawa, Canada > > Voice: +1.647.777.2635, Internal: (81) 32635 > > > - RGB -- Richard Guy Briggs <rgb@redhat.com> Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-28 19:28 ` Richard Guy Briggs @ 2016-04-28 19:32 ` Peter Hurley 0 siblings, 0 replies; 13+ messages in thread From: Peter Hurley @ 2016-04-28 19:32 UTC (permalink / raw) To: Richard Guy Briggs; +Cc: linux-audit, pmoore, linux-kernel, sgrubb, eparis On 04/28/2016 12:28 PM, Richard Guy Briggs wrote: > On 16/04/27, Peter Hurley wrote: >> On 04/27/2016 06:31 PM, Richard Guy Briggs wrote: >>> On 16/04/22, Peter Hurley wrote: >>>> On 04/21/2016 11:14 AM, Richard Guy Briggs wrote: >>>>> The tty field was missing from AUDIT_LOGIN events. >>>>> >>>>> Refactor code to create a new function audit_get_tty(), using it to >>>>> replace the call in audit_log_task_info() and to add it to >>>>> audit_log_set_loginuid(). Lock and bump the kref to protect it, adding >>>>> audit_put_tty() alias to decrement it. >>>>> >>>>> Signed-off-by: Richard Guy Briggs <rgb@redhat.com> >>>>> --- >>>>> >>>>> V4: Add missing prototype for audit_put_tty() when audit syscall is not >>>>> enabled (MIPS). >>>>> >>>>> V3: Introduce audit_put_tty() alias to decrement kref. >>>>> >>>>> V2: Use kref to protect tty signal struct while in use. >>>>> >>>>> --- >>>>> >>>>> include/linux/audit.h | 24 ++++++++++++++++++++++++ >>>>> kernel/audit.c | 18 +++++------------- >>>>> kernel/auditsc.c | 8 ++++++-- >>>>> 3 files changed, 35 insertions(+), 15 deletions(-) >>>>> >>>>> diff --git a/include/linux/audit.h b/include/linux/audit.h >>>>> index b40ed5d..32cdafb 100644 >>>>> --- a/include/linux/audit.h >>>>> +++ b/include/linux/audit.h >>>>> @@ -26,6 +26,7 @@ >>>>> #include <linux/sched.h> >>>>> #include <linux/ptrace.h> >>>>> #include <uapi/linux/audit.h> >>>>> +#include <linux/tty.h> >>>>> >>>>> #define AUDIT_INO_UNSET ((unsigned long)-1) >>>>> #define AUDIT_DEV_UNSET ((dev_t)-1) >>>>> @@ -343,6 +344,23 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) >>>>> return tsk->sessionid; >>>>> } >>>>> >>>>> +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) >>>>> +{ >>>>> + struct tty_struct *tty = NULL; >>>>> + unsigned long flags; >>>>> + >>>>> + spin_lock_irqsave(&tsk->sighand->siglock, flags); >>>>> + if (tsk->signal) >>>>> + tty = tty_kref_get(tsk->signal->tty); >>>>> + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); >>>> >>>> >>>> Not that I'm objecting because I get that you're just refactoring >>>> existing code, but I thought I'd point out some stuff. >>>> >>>> 1. There's no need to check if signal_struct is NULL (ie. tsk->signal) >>>> because if it is, this will blow up trying to dereference the >>>> sighand_struct (ie tsk->sighand). >>> >>> Ok. This logic goes back 10 years and one month less two days. (45d9bb0e) >>> >>>> 2. The existing usage is always tsk==current >>> >>> My understanding is that when it is called via: >>> >>> copy_process() >>> audit_free() >>> __audit_free() >>> audit_log_exit() >>> audit_log_task_info() >>> >>> then tsk != current. >> >> While it's true that tsk != current here, everything relevant to tty >> in task_struct is the same because the nascent task is not even half-done. >> So tsk->sighand == current->sighand, tsk->signal == current->signal etc. > > I agree this is true except in the case of !CLONE_SIGHAND, if it fails > after copy_sighand() or copy_signal() then it would be null and would > get freed before audit_free() is called. By the time tty gets copied > from current in this case, it is past the point of failure in > copy_process(). Oh, right. >> If you're uncomfortable with pass-through execution like that, then the >> simple solution is: >> >> struct tty_struct *tty = NULL; >> >> /* tsk != current when copy_process() failed */ >> if (tsk == current) >> tty = get_current_tty(); >> >> because tty_kref_put(tty) accepts NULL tty and (obviously) so does >> tty_name(tty). > > Given the circumstances above, this appears reasonable to me at first > look. Ok. I'll spend more analysis time before I actually submit a patch for this. >>> This appears to be the only case which appears to >>> force lugging around tsk. This is noted in that commit referenced >>> above. >>> >>>> 3. If the idea is to make this invulnerable to tsk being gone, then >>>> the usage is unsafe anyway. >>>> >>>> >>>> So ultimately (but not necessarily for this patch) I'd prefer that either >>>> a. audit use existing tty api instead of open-coding, or >>>> b. add any tty api functions required. >>> >>> This latter option did cross my mind... >>> >>>> Peter Hurley >>>> >>>>> + return tty; >>>>> +} >>>>> + >>>>> +static inline void audit_put_tty(struct tty_struct *tty) >>>>> +{ >>>>> + tty_kref_put(tty); >>>>> +} >>>>> + >>>>> extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); >>>>> extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); >>>>> extern void __audit_bprm(struct linux_binprm *bprm); >>>>> @@ -500,6 +518,12 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) >>>>> { >>>>> return -1; >>>>> } >>>>> +static inline struct tty_struct *audit_get_tty(struct task_struct *tsk) >>>>> +{ >>>>> + return NULL; >>>>> +} >>>>> +static inline void audit_put_tty(struct tty_struct *tty) >>>>> +{ } >>>>> static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) >>>>> { } >>>>> static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, >>>>> diff --git a/kernel/audit.c b/kernel/audit.c >>>>> index 3a3e5de..7edd776 100644 >>>>> --- a/kernel/audit.c >>>>> +++ b/kernel/audit.c >>>>> @@ -64,7 +64,6 @@ >>>>> #include <linux/security.h> >>>>> #endif >>>>> #include <linux/freezer.h> >>>>> -#include <linux/tty.h> >>>>> #include <linux/pid_namespace.h> >>>>> #include <net/netns/generic.h> >>>>> >>>>> @@ -1873,21 +1872,14 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) >>>>> { >>>>> const struct cred *cred; >>>>> char comm[sizeof(tsk->comm)]; >>>>> - char *tty; >>>>> + struct tty_struct *tty; >>>>> >>>>> if (!ab) >>>>> return; >>>>> >>>>> /* tsk == current */ >>>>> cred = current_cred(); >>>>> - >>>>> - spin_lock_irq(&tsk->sighand->siglock); >>>>> - if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) >>>>> - tty = tsk->signal->tty->name; >>>>> - else >>>>> - tty = "(none)"; >>>>> - spin_unlock_irq(&tsk->sighand->siglock); >>>>> - >>>>> + tty = audit_get_tty(tsk); >>>>> audit_log_format(ab, >>>>> " ppid=%d pid=%d auid=%u uid=%u gid=%u" >>>>> " euid=%u suid=%u fsuid=%u" >>>>> @@ -1903,11 +1895,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) >>>>> from_kgid(&init_user_ns, cred->egid), >>>>> from_kgid(&init_user_ns, cred->sgid), >>>>> from_kgid(&init_user_ns, cred->fsgid), >>>>> - tty, audit_get_sessionid(tsk)); >>>>> - >>>>> + tty ? tty_name(tty) : "(none)", >>>>> + audit_get_sessionid(tsk)); >>>>> + audit_put_tty(tty); >>>>> audit_log_format(ab, " comm="); >>>>> audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); >>>>> - >>>>> audit_log_d_path_exe(ab, tsk->mm); >>>>> audit_log_task_context(ab); >>>>> } >>>>> diff --git a/kernel/auditsc.c b/kernel/auditsc.c >>>>> index 195ffae..71e14d8 100644 >>>>> --- a/kernel/auditsc.c >>>>> +++ b/kernel/auditsc.c >>>>> @@ -1980,6 +1980,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, >>>>> { >>>>> struct audit_buffer *ab; >>>>> uid_t uid, oldloginuid, loginuid; >>>>> + struct tty_struct *tty; >>>>> >>>>> if (!audit_enabled) >>>>> return; >>>>> @@ -1987,14 +1988,17 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, >>>>> uid = from_kuid(&init_user_ns, task_uid(current)); >>>>> oldloginuid = from_kuid(&init_user_ns, koldloginuid); >>>>> loginuid = from_kuid(&init_user_ns, kloginuid), >>>>> + tty = audit_get_tty(current); >>>>> >>>>> ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); >>>>> if (!ab) >>>>> return; >>>>> audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); >>>>> audit_log_task_context(ab); >>>>> - audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", >>>>> - oldloginuid, loginuid, oldsessionid, sessionid, !rc); >>>>> + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", >>>>> + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", >>>>> + oldsessionid, sessionid, !rc); >>>>> + audit_put_tty(tty); >>>>> audit_log_end(ab); >>>>> } >>>>> >>>>> >>>> >>> >>> - RGB >>> >>> -- >>> Richard Guy Briggs <rgb@redhat.com> >>> Kernel Security Engineering, Base Operating Systems, Red Hat >>> Remote, Ottawa, Canada >>> Voice: +1.647.777.2635, Internal: (81) 32635 >>> >> > > - RGB > > -- > Richard Guy Briggs <rgb@redhat.com> > Kernel Security Engineering, Base Operating Systems, Red Hat > Remote, Ottawa, Canada > Voice: +1.647.777.2635, Internal: (81) 32635 > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH V4] audit: add tty field to LOGIN event 2016-04-28 1:31 ` Richard Guy Briggs 2016-04-28 3:05 ` Peter Hurley @ 2016-04-28 20:07 ` Paul Moore 1 sibling, 0 replies; 13+ messages in thread From: Paul Moore @ 2016-04-28 20:07 UTC (permalink / raw) To: Richard Guy Briggs, Peter Hurley; +Cc: linux-audit, linux-kernel On Wed, Apr 27, 2016 at 9:31 PM, Richard Guy Briggs <rgb@redhat.com> wrote: > On 16/04/22, Peter Hurley wrote: >> 2. The existing usage is always tsk==current > > My understanding is that when it is called via: > > copy_process() > audit_free() > __audit_free() > audit_log_exit() > audit_log_task_info() > > then tsk != current. This appears to be the only case which appears to > force lugging around tsk. This is noted in that commit referenced > above. In the case where copy_process() ends up calling __audit_free(), the call to audit_log_exit() is conditional on the audit context in_syscall field being true and unless I missed something, the copied process' audit context should not have in_syscall set to true. -- paul moore www.paul-moore.com ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2016-04-28 20:07 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-04-21 18:14 [PATCH V4] audit: add tty field to LOGIN event Richard Guy Briggs 2016-04-22 1:29 ` Paul Moore 2016-04-22 3:50 ` Richard Guy Briggs 2016-04-22 15:02 ` Paul Moore 2016-04-22 13:13 ` Steve Grubb 2016-04-22 17:16 ` Peter Hurley 2016-04-26 22:34 ` Paul Moore 2016-04-27 0:57 ` Peter Hurley 2016-04-28 1:31 ` Richard Guy Briggs 2016-04-28 3:05 ` Peter Hurley 2016-04-28 19:28 ` Richard Guy Briggs 2016-04-28 19:32 ` Peter Hurley 2016-04-28 20:07 ` Paul Moore
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox