[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[RFC][PATCH] (version 2) Introduce /proc/$$/loginuid



This patch finishes some of the cleanup of the last patch which moved
loginuid into the task_struct, and introduces /proc/$$/loginuid.  The
only comment I can think of which I haven't yet integrated was getting
rid of the get_free_page() in proc_loginuid_read().  I had problems when
I tried to do that earlier, but those were probably due to the loginuid
in audit_context problem.

thanks,
-serge
-- 
Serge Hallyn <serue us ibm com>
Index: linux-2.6.11-rc1-bk5/fs/proc/base.c
===================================================================
--- linux-2.6.11-rc1-bk5.orig/fs/proc/base.c	2005-01-17 10:16:18.000000000 -0600
+++ linux-2.6.11-rc1-bk5/fs/proc/base.c	2005-01-17 11:43:11.000000000 -0600
@@ -71,6 +71,9 @@ enum pid_directory_inos {
 	PROC_TGID_ATTR_EXEC,
 	PROC_TGID_ATTR_FSCREATE,
 #endif
+#ifdef CONFIG_AUDIT
+	PROC_TGID_LOGINUID,
+#endif
 	PROC_TGID_FD_DIR,
 	PROC_TID_INO,
 	PROC_TID_STATUS,
@@ -97,6 +100,9 @@ enum pid_directory_inos {
 	PROC_TID_ATTR_EXEC,
 	PROC_TID_ATTR_FSCREATE,
 #endif
+#ifdef CONFIG_AUDIT
+	PROC_TID_LOGINUID,
+#endif
 	PROC_TID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
 };
 
@@ -133,6 +139,9 @@ static struct pid_entry tgid_base_stuff[
 #ifdef CONFIG_SCHEDSTATS
 	E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO),
 #endif
+#ifdef CONFIG_AUDIT
+	E(PROC_TGID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
+#endif
 	{0,0,NULL,0}
 };
 static struct pid_entry tid_base_stuff[] = {
@@ -158,6 +167,9 @@ static struct pid_entry tid_base_stuff[]
 #ifdef CONFIG_SCHEDSTATS
 	E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO),
 #endif
+#ifdef CONFIG_AUDIT
+	E(PROC_TID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
+#endif
 	{0,0,NULL,0}
 };
 
@@ -661,6 +673,78 @@ static struct inode_operations proc_mem_
 	.permission	= proc_permission,
 };
 
+#ifdef CONFIG_AUDIT
+static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
+				  size_t count, loff_t *ppos)
+{
+	struct inode * inode = file->f_dentry->d_inode;
+	struct task_struct *task = proc_task(inode);
+	unsigned long page;
+	ssize_t length;
+
+	if (count > PAGE_SIZE)
+		count = PAGE_SIZE;
+	if (!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+
+	length = snprintf((char *)page, count, "%u\n", task->loginuid);
+
+	if (length >= 0)
+		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
+	free_page(page);
+	return length;
+}
+
+static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
+				   size_t count, loff_t *ppos)
+{ 
+	struct inode * inode = file->f_dentry->d_inode;
+	char *page, *tmp;
+	ssize_t length;
+	struct task_struct *task = proc_task(inode);
+	uid_t loginuid;
+
+	if (!capable(CAP_AUDIT_CONTROL))
+		return -EPERM;
+
+	if (current != task)
+		return -EPERM;
+
+	if (count > PAGE_SIZE)
+		count = PAGE_SIZE;
+
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+	page = (char*)__get_free_page(GFP_USER);
+	if (!page)
+		return -ENOMEM;
+	length = -EFAULT;
+	if (copy_from_user(page, buf, count))
+		goto out_free_page;
+
+	loginuid = simple_strtoul(page, &tmp, 10);
+	if (tmp == page) {
+		length = -EINVAL;
+		goto out_free_page;
+
+	}
+	length = audit_set_loginuid(task, loginuid);
+	if (length == 0)
+		length = count;
+
+out_free_page:
+	free_page((unsigned long) page);
+	return length;
+}
+
+static struct file_operations proc_loginuid_operations = {
+	.read		= proc_loginuid_read,
+	.write		= proc_loginuid_write,
+};
+#endif
+
 static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
@@ -1336,6 +1420,12 @@ static struct dentry *proc_pident_lookup
 			ei->op.proc_read = proc_pid_schedstat;
 			break;
 #endif
+#ifdef CONFIG_AUDIT
+		case PROC_TID_LOGINUID:
+		case PROC_TGID_LOGINUID:
+			inode->i_fop = &proc_loginuid_operations;
+			break;
+#endif
 		default:
 			printk("procfs: impossible type (%d)",p->type);
 			iput(inode);
Index: linux-2.6.11-rc1-bk5/include/linux/audit.h
===================================================================
--- linux-2.6.11-rc1-bk5.orig/include/linux/audit.h	2005-01-17 10:46:10.000000000 -0600
+++ linux-2.6.11-rc1-bk5/include/linux/audit.h	2005-01-17 11:21:20.000000000 -0600
@@ -114,12 +114,6 @@ struct audit_status {
 	__u32		backlog;	/* messages waiting in queue */
 };
 
-struct audit_login {
-	__u32		loginuid;
-	int		msglen;
-	char		msg[1024];
-};
-
 struct audit_rule {		/* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
 	__u32		flags;	/* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
 	__u32		action;	/* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
@@ -154,7 +148,6 @@ extern int  audit_receive_filter(int typ
 				 void *data);
 extern void audit_get_stamp(struct audit_context *ctx,
 			    struct timespec *t, int *serial);
-extern int  audit_set_loginuid(struct task_struct *tsk, uid_t loginuid);
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
@@ -193,6 +186,7 @@ extern void		    audit_send_reply(int pi
 					     int done, int multi,
 					     void *payload, int size);
 extern void		    audit_log_lost(const char *message);
+extern int  audit_set_loginuid(struct task_struct *tsk, uid_t loginuid);
 #else
 #define audit_log(t,f,...) do { ; } while (0)
 #define audit_log_start(t) ({ NULL; })
@@ -206,6 +200,7 @@ extern void		    audit_log_lost(const ch
 #define audit_set_backlog_limit(l) do { ; } while (0)
 #define audit_set_enabled(s) do { ; } while (0)
 #define audit_set_failure(s) do { ; } while (0)
+#define audit_set_loginuid(t,l) do { t->loginuid = l; } while (0)
 #endif
 #endif
 #endif
Index: linux-2.6.11-rc1-bk5/init/main.c
===================================================================
--- linux-2.6.11-rc1-bk5.orig/init/main.c	2005-01-17 12:07:24.000000000 -0600
+++ linux-2.6.11-rc1-bk5/init/main.c	2005-01-17 12:08:32.000000000 -0600
@@ -674,6 +674,8 @@ static int init(void * unused)
 	free_initmem();
 	unlock_kernel();
 
+	current->loginuid = -1;
+
 	system_state = SYSTEM_RUNNING;
 	numa_default_policy();
 
Index: linux-2.6.11-rc1-bk5/kernel/audit.c
===================================================================
--- linux-2.6.11-rc1-bk5.orig/kernel/audit.c	2005-01-17 10:45:58.000000000 -0600
+++ linux-2.6.11-rc1-bk5/kernel/audit.c	2005-01-17 12:21:34.000000000 -0600
@@ -312,7 +312,6 @@ int audit_netlink_ok(kernel_cap_t eff_ca
 		case AUDIT_GET:
 		case AUDIT_LIST:
 		case AUDIT_SET:
-		case AUDIT_LOGIN:
 		case AUDIT_ADD:
 		case AUDIT_DEL:
 			if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
@@ -336,7 +335,6 @@ static int audit_receive_msg(struct sk_b
 	u32			uid, pid, seq;
 	void			*data;
 	struct audit_status	*status_get, status_set;
-	struct audit_login	*login;
 	int			err;
 	struct audit_buffer	*ab;
 	u16			msg_type = nlh->nlmsg_type;
@@ -399,14 +397,6 @@ static int audit_receive_msg(struct sk_b
 		ab->pid  = pid;
 		audit_log_end(ab);
 		break;
-	case AUDIT_LOGIN:
-		if (nlh->nlmsg_len < sizeof(struct audit_login))
-			return -EINVAL;
-		login = (struct audit_login *)data;
-#ifdef CONFIG_AUDITSYSCALL
-		err = audit_set_loginuid(current, login->loginuid);
-#endif
-		break;
 	case AUDIT_ADD:
 	case AUDIT_DEL:
 		if (nlh->nlmsg_len < sizeof(struct audit_rule))
@@ -836,3 +826,21 @@ void audit_log(struct audit_context *ctx
 		audit_log_end(ab);
 	}
 }
+
+int audit_set_loginuid(struct task_struct *tsk, uid_t loginuid)
+{
+	struct audit_buffer *ab;
+
+	ab = audit_log_start(NULL);
+	if (ab) {
+		audit_log_format(ab, "login pid=%d uid=%u old loginuid=%u"
+					" new loginuid=%u",
+				 tsk->pid, tsk->uid, tsk->loginuid, loginuid);
+		ab->type = AUDIT_LOGIN;
+		ab->pid  = tsk->pid;
+		audit_log_end(ab);
+	}
+
+	tsk->loginuid = loginuid;
+	return 0;
+}
Index: linux-2.6.11-rc1-bk5/kernel/auditsc.c
===================================================================
--- linux-2.6.11-rc1-bk5.orig/kernel/auditsc.c	2005-01-17 10:54:01.000000000 -0600
+++ linux-2.6.11-rc1-bk5/kernel/auditsc.c	2005-01-17 11:51:27.000000000 -0600
@@ -527,9 +527,6 @@ int audit_alloc(struct task_struct *tsk)
 	struct audit_context *context;
 	enum audit_state     state;
 
-	/* Preserve login uid */
-	tsk->loginuid = current->loginuid;
-
 	if (likely(!audit_enabled))
 		return 0; /* Return if not auditing. */
 
@@ -898,21 +895,3 @@ void audit_get_stamp(struct audit_contex
 		*serial = 0;
 	}
 }
-
-int audit_set_loginuid(struct task_struct *tsk, uid_t loginuid)
-{
-	struct audit_buffer	*ab;
-
-	ab = audit_log_start(NULL);
-	if (ab) {
-		audit_log_format(ab, "login pid=%d uid=%u old loginuid=%u"
-					" new loginuid=%u",
-				 tsk->pid, tsk->uid, tsk->loginuid, loginuid)
-		ab->type = AUDIT_LOGIN;
-		ab->pid  = pid;
-		audit_log_end(ab);
-	}
-
-	tsk->loginuid = loginuid;
-	return 0;
-}
Index: linux-2.6.11-rc1-bk5/kernel/fork.c
===================================================================
--- linux-2.6.11-rc1-bk5.orig/kernel/fork.c	2005-01-17 10:16:23.000000000 -0600
+++ linux-2.6.11-rc1-bk5/kernel/fork.c	2005-01-17 11:51:42.000000000 -0600
@@ -909,6 +909,7 @@ static task_t *copy_process(unsigned lon
 		goto bad_fork_cleanup_policy;
 	if ((retval = audit_alloc(p)))
 		goto bad_fork_cleanup_security;
+	p->loginuid = current->loginuid;
 	/* copy all the process information */
 	if ((retval = copy_semundo(clone_flags, p)))
 		goto bad_fork_cleanup_audit;

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]