PROC_TGID_ATTR_PREV,
PROC_TGID_ATTR_EXEC,
PROC_TGID_ATTR_FSCREATE,
+#endif
+#ifdef CONFIG_AUDITSYSCALL
+ PROC_TGID_LOGINUID,
#endif
PROC_TGID_FD_DIR,
PROC_TGID_OOM_SCORE,
PROC_TID_ATTR_PREV,
PROC_TID_ATTR_EXEC,
PROC_TID_ATTR_FSCREATE,
+#endif
+#ifdef CONFIG_AUDITSYSCALL
+ PROC_TID_LOGINUID,
#endif
PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */
PROC_TID_OOM_SCORE,
#endif
E(PROC_TGID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
E(PROC_TGID_OOM_ADJUST,"oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
+#ifdef CONFIG_AUDITSYSCALL
+ E(PROC_TGID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
+#endif
{0,0,NULL,0}
};
static struct pid_entry tid_base_stuff[] = {
#endif
E(PROC_TID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
E(PROC_TID_OOM_ADJUST, "oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
+#ifdef CONFIG_AUDITSYSCALL
+ E(PROC_TID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
+#endif
{0,0,NULL,0}
};
.permission = proc_permission,
};
+#ifdef CONFIG_AUDITSYSCALL
+#define TMPBUFLEN 21
+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);
+ ssize_t length;
+ char tmpbuf[TMPBUFLEN];
+
+ length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
+ audit_get_loginuid(task->audit_context));
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, 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->audit_context, loginuid);
+ if (likely(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;
case PROC_TGID_OOM_ADJUST:
inode->i_fop = &proc_oom_adjust_operations;
break;
+#ifdef CONFIG_AUDITSYSCALL
+ 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);
__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 */
extern void audit_get_stamp(struct audit_context *ctx,
struct timespec *t, int *serial);
extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid);
+extern uid_t audit_get_loginuid(struct audit_context *ctx);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
#define audit_inode(n,i,d) do { ; } while (0)
+#define audit_get_loginuid(c) ({ -1; })
#endif
#ifdef CONFIG_AUDIT
int count; /* Times requeued */
};
+void audit_set_type(struct audit_buffer *ab, int type)
+{
+ ab->type = type;
+}
+
struct audit_entry {
struct list_head list;
struct audit_rule rule;
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))
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;
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;
- ab = audit_log_start(NULL);
- if (ab) {
- audit_log_format(ab, "login pid=%d uid=%d loginuid=%d"
- " length=%d msg='%.1024s'",
- pid, uid,
- login->loginuid,
- login->msglen,
- login->msg);
- ab->type = AUDIT_LOGIN;
- ab->pid = pid;
- audit_log_end(ab);
- }
-#ifdef CONFIG_AUDITSYSCALL
- err = audit_set_loginuid(current->audit_context,
- login->loginuid);
-#endif
- break;
case AUDIT_ADD:
case AUDIT_DEL:
if (nlh->nlmsg_len < sizeof(struct audit_rule))
/* Preserve login uid */
context->loginuid = -1;
- if (tsk->audit_context)
- context->loginuid = tsk->audit_context->loginuid;
+ if (current->audit_context)
+ context->loginuid = current->audit_context->loginuid;
tsk->audit_context = context;
set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
}
}
+extern int audit_set_type(struct audit_buffer *ab, int type);
+
int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid)
{
if (ctx) {
- if (loginuid < 0)
- return -EINVAL;
+ 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",
+ ctx->pid, ctx->uid, ctx->loginuid, loginuid);
+ audit_set_type(ab, AUDIT_LOGIN);
+ audit_log_end(ab);
+ }
ctx->loginuid = loginuid;
}
return 0;
}
+
+uid_t audit_get_loginuid(struct audit_context *ctx)
+{
+ return ctx ? ctx->loginuid : -1;
+}