Loading kernel/audit.c +57 −27 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ #include <linux/rcupdate.h> #include <linux/mutex.h> #include <linux/gfp.h> #include <linux/pid.h> #include <linux/audit.h> Loading Loading @@ -117,7 +118,7 @@ struct audit_net { * or the included spinlock for writing. */ static struct auditd_connection { int pid; struct pid *pid; u32 portid; struct net *net; spinlock_t lock; Loading Loading @@ -220,17 +221,40 @@ struct audit_reply { * Description: * Return 1 if the task is a registered audit daemon, 0 otherwise. */ int auditd_test_task(const struct task_struct *task) int auditd_test_task(struct task_struct *task) { int rc; rcu_read_lock(); rc = (auditd_conn.pid && task->tgid == auditd_conn.pid ? 1 : 0); rc = (auditd_conn.pid && auditd_conn.pid == task_tgid(task) ? 1 : 0); rcu_read_unlock(); return rc; } /** * auditd_pid_vnr - Return the auditd PID relative to the namespace * @auditd: the auditd connection * * Description: * Returns the PID in relation to the namespace, 0 on failure. This function * takes the RCU read lock internally, but if the caller needs to protect the * auditd_connection pointer it should take the RCU read lock as well. */ static pid_t auditd_pid_vnr(const struct auditd_connection *auditd) { pid_t pid; rcu_read_lock(); if (!auditd || !auditd->pid) pid = 0; else pid = pid_vnr(auditd->pid); rcu_read_unlock(); return pid; } /** * audit_get_sk - Return the audit socket for the given network namespace * @net: the destination network namespace Loading Loading @@ -428,12 +452,17 @@ static int audit_set_failure(u32 state) * This function will obtain and drop network namespace references as * necessary. */ static void auditd_set(int pid, u32 portid, struct net *net) static void auditd_set(struct pid *pid, u32 portid, struct net *net) { unsigned long flags; spin_lock_irqsave(&auditd_conn.lock, flags); auditd_conn.pid = pid; if (auditd_conn.pid) put_pid(auditd_conn.pid); if (pid) auditd_conn.pid = get_pid(pid); else auditd_conn.pid = NULL; auditd_conn.portid = portid; if (auditd_conn.net) put_net(auditd_conn.net); Loading Loading @@ -1059,11 +1088,13 @@ static int audit_set_feature(struct sk_buff *skb) return 0; } static int audit_replace(pid_t pid) static int audit_replace(struct pid *pid) { pid_t pvnr; struct sk_buff *skb; skb = audit_make_reply(0, AUDIT_REPLACE, 0, 0, &pid, sizeof(pid)); pvnr = pid_vnr(pid); skb = audit_make_reply(0, AUDIT_REPLACE, 0, 0, &pvnr, sizeof(pvnr)); if (!skb) return -ENOMEM; return auditd_send_unicast_skb(skb); Loading Loading @@ -1093,9 +1124,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) memset(&s, 0, sizeof(s)); s.enabled = audit_enabled; s.failure = audit_failure; rcu_read_lock(); s.pid = auditd_conn.pid; rcu_read_unlock(); /* NOTE: use pid_vnr() so the PID is relative to the current * namespace */ s.pid = auditd_pid_vnr(&auditd_conn); s.rate_limit = audit_rate_limit; s.backlog_limit = audit_backlog_limit; s.lost = atomic_read(&audit_lost); Loading @@ -1121,36 +1152,36 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return err; } if (s.mask & AUDIT_STATUS_PID) { /* NOTE: we are using task_tgid_vnr() below because * the s.pid value is relative to the namespace * of the caller; at present this doesn't matter * much since you can really only run auditd * from the initial pid namespace, but something * to keep in mind if this changes */ int new_pid = s.pid; /* NOTE: we are using the vnr PID functions below * because the s.pid value is relative to the * namespace of the caller; at present this * doesn't matter much since you can really only * run auditd from the initial pid namespace, but * something to keep in mind if this changes */ pid_t new_pid = s.pid; pid_t auditd_pid; pid_t requesting_pid = task_tgid_vnr(current); struct pid *req_pid = task_tgid(current); /* sanity check - PID values must match */ if (new_pid != pid_vnr(req_pid)) return -EINVAL; /* test the auditd connection */ audit_replace(requesting_pid); audit_replace(req_pid); rcu_read_lock(); auditd_pid = auditd_conn.pid; auditd_pid = auditd_pid_vnr(&auditd_conn); /* only the current auditd can unregister itself */ if ((!new_pid) && (requesting_pid != auditd_pid)) { rcu_read_unlock(); if ((!new_pid) && (new_pid != auditd_pid)) { audit_log_config_change("audit_pid", new_pid, auditd_pid, 0); return -EACCES; } /* replacing a healthy auditd is not allowed */ if (auditd_pid && new_pid) { rcu_read_unlock(); audit_log_config_change("audit_pid", new_pid, auditd_pid, 0); return -EEXIST; } rcu_read_unlock(); if (audit_enabled != AUDIT_OFF) audit_log_config_change("audit_pid", new_pid, Loading @@ -1158,8 +1189,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (new_pid) { /* register a new auditd connection */ auditd_set(new_pid, NETLINK_CB(skb).portid, auditd_set(req_pid, NETLINK_CB(skb).portid, sock_net(NETLINK_CB(skb).sk)); /* try to process any backlog */ wake_up_interruptible(&kauditd_wait); Loading kernel/audit.h +1 −1 Original line number Diff line number Diff line Loading @@ -218,7 +218,7 @@ extern void audit_log_name(struct audit_context *context, struct audit_names *n, const struct path *path, int record_num, int *call_panic); extern int auditd_test_task(const struct task_struct *task); extern int auditd_test_task(struct task_struct *task); #define AUDIT_INODE_BUCKETS 32 extern struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; Loading Loading
kernel/audit.c +57 −27 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ #include <linux/rcupdate.h> #include <linux/mutex.h> #include <linux/gfp.h> #include <linux/pid.h> #include <linux/audit.h> Loading Loading @@ -117,7 +118,7 @@ struct audit_net { * or the included spinlock for writing. */ static struct auditd_connection { int pid; struct pid *pid; u32 portid; struct net *net; spinlock_t lock; Loading Loading @@ -220,17 +221,40 @@ struct audit_reply { * Description: * Return 1 if the task is a registered audit daemon, 0 otherwise. */ int auditd_test_task(const struct task_struct *task) int auditd_test_task(struct task_struct *task) { int rc; rcu_read_lock(); rc = (auditd_conn.pid && task->tgid == auditd_conn.pid ? 1 : 0); rc = (auditd_conn.pid && auditd_conn.pid == task_tgid(task) ? 1 : 0); rcu_read_unlock(); return rc; } /** * auditd_pid_vnr - Return the auditd PID relative to the namespace * @auditd: the auditd connection * * Description: * Returns the PID in relation to the namespace, 0 on failure. This function * takes the RCU read lock internally, but if the caller needs to protect the * auditd_connection pointer it should take the RCU read lock as well. */ static pid_t auditd_pid_vnr(const struct auditd_connection *auditd) { pid_t pid; rcu_read_lock(); if (!auditd || !auditd->pid) pid = 0; else pid = pid_vnr(auditd->pid); rcu_read_unlock(); return pid; } /** * audit_get_sk - Return the audit socket for the given network namespace * @net: the destination network namespace Loading Loading @@ -428,12 +452,17 @@ static int audit_set_failure(u32 state) * This function will obtain and drop network namespace references as * necessary. */ static void auditd_set(int pid, u32 portid, struct net *net) static void auditd_set(struct pid *pid, u32 portid, struct net *net) { unsigned long flags; spin_lock_irqsave(&auditd_conn.lock, flags); auditd_conn.pid = pid; if (auditd_conn.pid) put_pid(auditd_conn.pid); if (pid) auditd_conn.pid = get_pid(pid); else auditd_conn.pid = NULL; auditd_conn.portid = portid; if (auditd_conn.net) put_net(auditd_conn.net); Loading Loading @@ -1059,11 +1088,13 @@ static int audit_set_feature(struct sk_buff *skb) return 0; } static int audit_replace(pid_t pid) static int audit_replace(struct pid *pid) { pid_t pvnr; struct sk_buff *skb; skb = audit_make_reply(0, AUDIT_REPLACE, 0, 0, &pid, sizeof(pid)); pvnr = pid_vnr(pid); skb = audit_make_reply(0, AUDIT_REPLACE, 0, 0, &pvnr, sizeof(pvnr)); if (!skb) return -ENOMEM; return auditd_send_unicast_skb(skb); Loading Loading @@ -1093,9 +1124,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) memset(&s, 0, sizeof(s)); s.enabled = audit_enabled; s.failure = audit_failure; rcu_read_lock(); s.pid = auditd_conn.pid; rcu_read_unlock(); /* NOTE: use pid_vnr() so the PID is relative to the current * namespace */ s.pid = auditd_pid_vnr(&auditd_conn); s.rate_limit = audit_rate_limit; s.backlog_limit = audit_backlog_limit; s.lost = atomic_read(&audit_lost); Loading @@ -1121,36 +1152,36 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return err; } if (s.mask & AUDIT_STATUS_PID) { /* NOTE: we are using task_tgid_vnr() below because * the s.pid value is relative to the namespace * of the caller; at present this doesn't matter * much since you can really only run auditd * from the initial pid namespace, but something * to keep in mind if this changes */ int new_pid = s.pid; /* NOTE: we are using the vnr PID functions below * because the s.pid value is relative to the * namespace of the caller; at present this * doesn't matter much since you can really only * run auditd from the initial pid namespace, but * something to keep in mind if this changes */ pid_t new_pid = s.pid; pid_t auditd_pid; pid_t requesting_pid = task_tgid_vnr(current); struct pid *req_pid = task_tgid(current); /* sanity check - PID values must match */ if (new_pid != pid_vnr(req_pid)) return -EINVAL; /* test the auditd connection */ audit_replace(requesting_pid); audit_replace(req_pid); rcu_read_lock(); auditd_pid = auditd_conn.pid; auditd_pid = auditd_pid_vnr(&auditd_conn); /* only the current auditd can unregister itself */ if ((!new_pid) && (requesting_pid != auditd_pid)) { rcu_read_unlock(); if ((!new_pid) && (new_pid != auditd_pid)) { audit_log_config_change("audit_pid", new_pid, auditd_pid, 0); return -EACCES; } /* replacing a healthy auditd is not allowed */ if (auditd_pid && new_pid) { rcu_read_unlock(); audit_log_config_change("audit_pid", new_pid, auditd_pid, 0); return -EEXIST; } rcu_read_unlock(); if (audit_enabled != AUDIT_OFF) audit_log_config_change("audit_pid", new_pid, Loading @@ -1158,8 +1189,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (new_pid) { /* register a new auditd connection */ auditd_set(new_pid, NETLINK_CB(skb).portid, auditd_set(req_pid, NETLINK_CB(skb).portid, sock_net(NETLINK_CB(skb).sk)); /* try to process any backlog */ wake_up_interruptible(&kauditd_wait); Loading
kernel/audit.h +1 −1 Original line number Diff line number Diff line Loading @@ -218,7 +218,7 @@ extern void audit_log_name(struct audit_context *context, struct audit_names *n, const struct path *path, int record_num, int *call_panic); extern int auditd_test_task(const struct task_struct *task); extern int auditd_test_task(struct task_struct *task); #define AUDIT_INODE_BUCKETS 32 extern struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; Loading