diff options
Diffstat (limited to 'kernel/audit.c')
| -rw-r--r-- | kernel/audit.c | 117 | 
1 files changed, 46 insertions, 71 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index ea3b7b6191c..511488a7bc7 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -61,6 +61,7 @@  #include <linux/netlink.h>  #include <linux/freezer.h>  #include <linux/tty.h> +#include <linux/pid_namespace.h>  #include "audit.h" @@ -104,7 +105,7 @@ static int	audit_backlog_wait_time = 60 * HZ;  static int	audit_backlog_wait_overflow = 0;  /* The identity of the user shutting down the audit system. */ -uid_t		audit_sig_uid = -1; +kuid_t		audit_sig_uid = INVALID_UID;  pid_t		audit_sig_pid = -1;  u32		audit_sig_sid = 0; @@ -264,7 +265,7 @@ void audit_log_lost(const char *message)  }  static int audit_log_config_change(char *function_name, int new, int old, -				   uid_t loginuid, u32 sessionid, u32 sid, +				   kuid_t loginuid, u32 sessionid, u32 sid,  				   int allow_changes)  {  	struct audit_buffer *ab; @@ -272,7 +273,7 @@ static int audit_log_config_change(char *function_name, int new, int old,  	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);  	audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, -			 old, loginuid, sessionid); +			 old, from_kuid(&init_user_ns, loginuid), sessionid);  	if (sid) {  		char *ctx = NULL;  		u32 len; @@ -292,7 +293,7 @@ static int audit_log_config_change(char *function_name, int new, int old,  }  static int audit_do_config_change(char *function_name, int *to_change, -				  int new, uid_t loginuid, u32 sessionid, +				  int new, kuid_t loginuid, u32 sessionid,  				  u32 sid)  {  	int allow_changes, rc = 0, old = *to_change; @@ -319,21 +320,21 @@ static int audit_do_config_change(char *function_name, int *to_change,  	return rc;  } -static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sessionid, +static int audit_set_rate_limit(int limit, kuid_t loginuid, u32 sessionid,  				u32 sid)  {  	return audit_do_config_change("audit_rate_limit", &audit_rate_limit,  				      limit, loginuid, sessionid, sid);  } -static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sessionid, +static int audit_set_backlog_limit(int limit, kuid_t loginuid, u32 sessionid,  				   u32 sid)  {  	return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit,  				      limit, loginuid, sessionid, sid);  } -static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid) +static int audit_set_enabled(int state, kuid_t loginuid, u32 sessionid, u32 sid)  {  	int rc;  	if (state < AUDIT_OFF || state > AUDIT_LOCKED) @@ -348,7 +349,7 @@ static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid)  	return rc;  } -static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid) +static int audit_set_failure(int state, kuid_t loginuid, u32 sessionid, u32 sid)  {  	if (state != AUDIT_FAIL_SILENT  	    && state != AUDIT_FAIL_PRINTK @@ -467,24 +468,6 @@ static int kauditd_thread(void *dummy)  	return 0;  } -static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid) -{ -	struct task_struct *tsk; -	int err; - -	rcu_read_lock(); -	tsk = find_task_by_vpid(pid); -	if (!tsk) { -		rcu_read_unlock(); -		return -ESRCH; -	} -	get_task_struct(tsk); -	rcu_read_unlock(); -	err = tty_audit_push_task(tsk, loginuid, sessionid); -	put_task_struct(tsk); -	return err; -} -  int audit_send_list(void *_dest)  {  	struct audit_netlink_list *dest = _dest; @@ -588,6 +571,11 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)  {  	int err = 0; +	/* Only support the initial namespaces for now. */ +	if ((current_user_ns() != &init_user_ns) || +	    (task_active_pid_ns(current) != &init_pid_ns)) +		return -EPERM; +  	switch (msg_type) {  	case AUDIT_GET:  	case AUDIT_LIST: @@ -619,8 +607,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)  }  static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, -				     u32 pid, u32 uid, uid_t auid, u32 ses, -				     u32 sid) +				     kuid_t auid, u32 ses, u32 sid)  {  	int rc = 0;  	char *ctx = NULL; @@ -633,7 +620,9 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,  	*ab = audit_log_start(NULL, GFP_KERNEL, msg_type);  	audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u", -			 pid, uid, auid, ses); +			 task_tgid_vnr(current), +			 from_kuid(&init_user_ns, current_uid()), +			 from_kuid(&init_user_ns, auid), ses);  	if (sid) {  		rc = security_secid_to_secctx(sid, &ctx, &len);  		if (rc) @@ -649,13 +638,13 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,  static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  { -	u32			uid, pid, seq, sid; +	u32			seq, sid;  	void			*data;  	struct audit_status	*status_get, status_set;  	int			err;  	struct audit_buffer	*ab;  	u16			msg_type = nlh->nlmsg_type; -	uid_t			loginuid; /* loginuid of sender */ +	kuid_t			loginuid; /* loginuid of sender */  	u32			sessionid;  	struct audit_sig_info   *sig_data;  	char			*ctx = NULL; @@ -675,8 +664,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		return err;  	} -	pid  = NETLINK_CREDS(skb)->pid; -	uid  = NETLINK_CREDS(skb)->uid;  	loginuid = audit_get_loginuid(current);  	sessionid = audit_get_sessionid(current);  	security_task_getsecid(current, &sid); @@ -738,16 +725,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		if (!audit_enabled && msg_type != AUDIT_USER_AVC)  			return 0; -		err = audit_filter_user(&NETLINK_CB(skb)); +		err = audit_filter_user();  		if (err == 1) {  			err = 0;  			if (msg_type == AUDIT_USER_TTY) { -				err = audit_prepare_user_tty(pid, loginuid, +				err = tty_audit_push_task(current, loginuid,  							     sessionid);  				if (err)  					break;  			} -			audit_log_common_recv_msg(&ab, msg_type, pid, uid, +			audit_log_common_recv_msg(&ab, msg_type,  						  loginuid, sessionid, sid);  			if (msg_type != AUDIT_USER_TTY) @@ -763,7 +750,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  					size--;  				audit_log_n_untrustedstring(ab, data, size);  			} -			audit_set_pid(ab, pid); +			audit_set_pid(ab, NETLINK_CB(skb).pid);  			audit_log_end(ab);  		}  		break; @@ -772,8 +759,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		if (nlmsg_len(nlh) < sizeof(struct audit_rule))  			return -EINVAL;  		if (audit_enabled == AUDIT_LOCKED) { -			audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, -						  uid, loginuid, sessionid, sid); +			audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, +						  loginuid, sessionid, sid);  			audit_log_format(ab, " audit_enabled=%d res=0",  					 audit_enabled); @@ -783,7 +770,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		/* fallthrough */  	case AUDIT_LIST:  		err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, -					   uid, seq, data, nlmsg_len(nlh), +					   seq, data, nlmsg_len(nlh),  					   loginuid, sessionid, sid);  		break;  	case AUDIT_ADD_RULE: @@ -791,8 +778,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))  			return -EINVAL;  		if (audit_enabled == AUDIT_LOCKED) { -			audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, -						  uid, loginuid, sessionid, sid); +			audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, +						  loginuid, sessionid, sid);  			audit_log_format(ab, " audit_enabled=%d res=0",  					 audit_enabled); @@ -802,14 +789,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		/* fallthrough */  	case AUDIT_LIST_RULES:  		err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, -					   uid, seq, data, nlmsg_len(nlh), +					   seq, data, nlmsg_len(nlh),  					   loginuid, sessionid, sid);  		break;  	case AUDIT_TRIM:  		audit_trim_trees(); -		audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, -					  uid, loginuid, sessionid, sid); +		audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, +					  loginuid, sessionid, sid);  		audit_log_format(ab, " op=trim res=1");  		audit_log_end(ab); @@ -840,8 +827,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		/* OK, here comes... */  		err = audit_tag_tree(old, new); -		audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, -					  uid, loginuid, sessionid, sid); +		audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, +					  loginuid, sessionid, sid);  		audit_log_format(ab, " op=make_equiv old=");  		audit_log_untrustedstring(ab, old); @@ -866,7 +853,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  				security_release_secctx(ctx, len);  			return -ENOMEM;  		} -		sig_data->uid = audit_sig_uid; +		sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);  		sig_data->pid = audit_sig_pid;  		if (audit_sig_sid) {  			memcpy(sig_data->ctx, ctx, len); @@ -878,41 +865,29 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		break;  	case AUDIT_TTY_GET: {  		struct audit_tty_status s; -		struct task_struct *tsk; -		unsigned long flags; +		struct task_struct *tsk = current; -		rcu_read_lock(); -		tsk = find_task_by_vpid(pid); -		if (tsk && lock_task_sighand(tsk, &flags)) { -			s.enabled = tsk->signal->audit_tty != 0; -			unlock_task_sighand(tsk, &flags); -		} else -			err = -ESRCH; -		rcu_read_unlock(); +		spin_lock_irq(&tsk->sighand->siglock); +		s.enabled = tsk->signal->audit_tty != 0; +		spin_unlock_irq(&tsk->sighand->siglock); -		if (!err) -			audit_send_reply(NETLINK_CB(skb).pid, seq, -					 AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); +		audit_send_reply(NETLINK_CB(skb).pid, seq, +				 AUDIT_TTY_GET, 0, 0, &s, sizeof(s));  		break;  	}  	case AUDIT_TTY_SET: {  		struct audit_tty_status *s; -		struct task_struct *tsk; -		unsigned long flags; +		struct task_struct *tsk = current;  		if (nlh->nlmsg_len < sizeof(struct audit_tty_status))  			return -EINVAL;  		s = data;  		if (s->enabled != 0 && s->enabled != 1)  			return -EINVAL; -		rcu_read_lock(); -		tsk = find_task_by_vpid(pid); -		if (tsk && lock_task_sighand(tsk, &flags)) { -			tsk->signal->audit_tty = s->enabled != 0; -			unlock_task_sighand(tsk, &flags); -		} else -			err = -ESRCH; -		rcu_read_unlock(); + +		spin_lock_irq(&tsk->sighand->siglock); +		tsk->signal->audit_tty = s->enabled != 0; +		spin_unlock_irq(&tsk->sighand->siglock);  		break;  	}  	default:  |