diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2007-02-07 01:48:00 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2007-02-17 21:30:15 -0500 |
commit | db3495099d3d52854b13874905af6e40a91f4721 (patch) | |
tree | 5a832081d70dd9dabda3498baf40b7d6ced47f24 | |
parent | 6a01b07fae482f9b34491b317056c89d3b96ca2e (diff) |
[PATCH] AUDIT_FD_PAIR
Provide an audit record of the descriptor pair returned by pipe() and
socketpair(). Rewritten from the original posted to linux-audit by
John D. Ramsdell <ramsdell@mitre.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/pipe.c | 7 | ||||
-rw-r--r-- | include/linux/audit.h | 9 | ||||
-rw-r--r-- | kernel/auditsc.c | 40 | ||||
-rw-r--r-- | net/socket.c | 52 |
4 files changed, 95 insertions, 13 deletions
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/uio.h> | 16 | #include <linux/uio.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
19 | #include <linux/audit.h> | ||
19 | 20 | ||
20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
21 | #include <asm/ioctls.h> | 22 | #include <asm/ioctls.h> |
@@ -985,6 +986,10 @@ int do_pipe(int *fd) | |||
985 | goto err_fdr; | 986 | goto err_fdr; |
986 | fdw = error; | 987 | fdw = error; |
987 | 988 | ||
989 | error = audit_fd_pair(fdr, fdw); | ||
990 | if (error < 0) | ||
991 | goto err_fdw; | ||
992 | |||
988 | fd_install(fdr, fr); | 993 | fd_install(fdr, fr); |
989 | fd_install(fdw, fw); | 994 | fd_install(fdw, fw); |
990 | fd[0] = fdr; | 995 | fd[0] = fdr; |
@@ -992,6 +997,8 @@ int do_pipe(int *fd) | |||
992 | 997 | ||
993 | return 0; | 998 | return 0; |
994 | 999 | ||
1000 | err_fdw: | ||
1001 | put_unused_fd(fdw); | ||
995 | err_fdr: | 1002 | err_fdr: |
996 | put_unused_fd(fdr); | 1003 | put_unused_fd(fdr); |
997 | err_read_pipe: | 1004 | err_read_pipe: |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 0e07db6cc0d0..229fa012c893 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -89,6 +89,7 @@ | |||
89 | #define AUDIT_MQ_NOTIFY 1314 /* POSIX MQ notify record type */ | 89 | #define AUDIT_MQ_NOTIFY 1314 /* POSIX MQ notify record type */ |
90 | #define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */ | 90 | #define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */ |
91 | #define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */ | 91 | #define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */ |
92 | #define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */ | ||
92 | 93 | ||
93 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ | 94 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
94 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ | 95 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
@@ -387,6 +388,7 @@ extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode | |||
387 | extern int audit_bprm(struct linux_binprm *bprm); | 388 | extern int audit_bprm(struct linux_binprm *bprm); |
388 | extern int audit_socketcall(int nargs, unsigned long *args); | 389 | extern int audit_socketcall(int nargs, unsigned long *args); |
389 | extern int audit_sockaddr(int len, void *addr); | 390 | extern int audit_sockaddr(int len, void *addr); |
391 | extern int __audit_fd_pair(int fd1, int fd2); | ||
390 | extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); | 392 | extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); |
391 | extern int audit_set_macxattr(const char *name); | 393 | extern int audit_set_macxattr(const char *name); |
392 | extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr); | 394 | extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr); |
@@ -401,6 +403,12 @@ static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp) | |||
401 | return __audit_ipc_obj(ipcp); | 403 | return __audit_ipc_obj(ipcp); |
402 | return 0; | 404 | return 0; |
403 | } | 405 | } |
406 | static inline int audit_fd_pair(int fd1, int fd2) | ||
407 | { | ||
408 | if (unlikely(!audit_dummy_context())) | ||
409 | return __audit_fd_pair(fd1, fd2); | ||
410 | return 0; | ||
411 | } | ||
404 | static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) | 412 | static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) |
405 | { | 413 | { |
406 | if (unlikely(!audit_dummy_context())) | 414 | if (unlikely(!audit_dummy_context())) |
@@ -459,6 +467,7 @@ extern int audit_n_rules; | |||
459 | #define audit_ipc_set_perm(q,u,g,m) ({ 0; }) | 467 | #define audit_ipc_set_perm(q,u,g,m) ({ 0; }) |
460 | #define audit_bprm(p) ({ 0; }) | 468 | #define audit_bprm(p) ({ 0; }) |
461 | #define audit_socketcall(n,a) ({ 0; }) | 469 | #define audit_socketcall(n,a) ({ 0; }) |
470 | #define audit_fd_pair(n,a) ({ 0; }) | ||
462 | #define audit_sockaddr(len, addr) ({ 0; }) | 471 | #define audit_sockaddr(len, addr) ({ 0; }) |
463 | #define audit_avc_path(dentry, mnt) ({ 0; }) | 472 | #define audit_avc_path(dentry, mnt) ({ 0; }) |
464 | #define audit_set_macxattr(n) do { ; } while (0) | 473 | #define audit_set_macxattr(n) do { ; } while (0) |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 298897559ca4..359955800dd2 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -170,6 +170,11 @@ struct audit_aux_data_sockaddr { | |||
170 | char a[0]; | 170 | char a[0]; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | struct audit_aux_data_fd_pair { | ||
174 | struct audit_aux_data d; | ||
175 | int fd[2]; | ||
176 | }; | ||
177 | |||
173 | struct audit_aux_data_path { | 178 | struct audit_aux_data_path { |
174 | struct audit_aux_data d; | 179 | struct audit_aux_data d; |
175 | struct dentry *dentry; | 180 | struct dentry *dentry; |
@@ -961,6 +966,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
961 | audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); | 966 | audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); |
962 | break; } | 967 | break; } |
963 | 968 | ||
969 | case AUDIT_FD_PAIR: { | ||
970 | struct audit_aux_data_fd_pair *axs = (void *)aux; | ||
971 | audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]); | ||
972 | break; } | ||
973 | |||
964 | } | 974 | } |
965 | audit_log_end(ab); | 975 | audit_log_end(ab); |
966 | } | 976 | } |
@@ -1815,6 +1825,36 @@ int audit_socketcall(int nargs, unsigned long *args) | |||
1815 | } | 1825 | } |
1816 | 1826 | ||
1817 | /** | 1827 | /** |
1828 | * __audit_fd_pair - record audit data for pipe and socketpair | ||
1829 | * @fd1: the first file descriptor | ||
1830 | * @fd2: the second file descriptor | ||
1831 | * | ||
1832 | * Returns 0 for success or NULL context or < 0 on error. | ||
1833 | */ | ||
1834 | int __audit_fd_pair(int fd1, int fd2) | ||
1835 | { | ||
1836 | struct audit_context *context = current->audit_context; | ||
1837 | struct audit_aux_data_fd_pair *ax; | ||
1838 | |||
1839 | if (likely(!context)) { | ||
1840 | return 0; | ||
1841 | } | ||
1842 | |||
1843 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); | ||
1844 | if (!ax) { | ||
1845 | return -ENOMEM; | ||
1846 | } | ||
1847 | |||
1848 | ax->fd[0] = fd1; | ||
1849 | ax->fd[1] = fd2; | ||
1850 | |||
1851 | ax->d.type = AUDIT_FD_PAIR; | ||
1852 | ax->d.next = context->aux; | ||
1853 | context->aux = (void *)ax; | ||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | /** | ||
1818 | * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto | 1858 | * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto |
1819 | * @len: data length in user space | 1859 | * @len: data length in user space |
1820 | * @a: data address in kernel space | 1860 | * @a: data address in kernel space |
diff --git a/net/socket.c b/net/socket.c index 0778c5442411..9566e57ac7f5 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -1194,6 +1194,7 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, | |||
1194 | { | 1194 | { |
1195 | struct socket *sock1, *sock2; | 1195 | struct socket *sock1, *sock2; |
1196 | int fd1, fd2, err; | 1196 | int fd1, fd2, err; |
1197 | struct file *newfile1, *newfile2; | ||
1197 | 1198 | ||
1198 | /* | 1199 | /* |
1199 | * Obtain the first socket and check if the underlying protocol | 1200 | * Obtain the first socket and check if the underlying protocol |
@@ -1212,18 +1213,37 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, | |||
1212 | if (err < 0) | 1213 | if (err < 0) |
1213 | goto out_release_both; | 1214 | goto out_release_both; |
1214 | 1215 | ||
1215 | fd1 = fd2 = -1; | 1216 | fd1 = sock_alloc_fd(&newfile1); |
1217 | if (unlikely(fd1 < 0)) | ||
1218 | goto out_release_both; | ||
1216 | 1219 | ||
1217 | err = sock_map_fd(sock1); | 1220 | fd2 = sock_alloc_fd(&newfile2); |
1218 | if (err < 0) | 1221 | if (unlikely(fd2 < 0)) { |
1222 | put_filp(newfile1); | ||
1223 | put_unused_fd(fd1); | ||
1219 | goto out_release_both; | 1224 | goto out_release_both; |
1220 | fd1 = err; | 1225 | } |
1221 | 1226 | ||
1222 | err = sock_map_fd(sock2); | 1227 | err = sock_attach_fd(sock1, newfile1); |
1223 | if (err < 0) | 1228 | if (unlikely(err < 0)) { |
1224 | goto out_close_1; | 1229 | goto out_fd2; |
1225 | fd2 = err; | 1230 | } |
1231 | |||
1232 | err = sock_attach_fd(sock2, newfile2); | ||
1233 | if (unlikely(err < 0)) { | ||
1234 | fput(newfile1); | ||
1235 | goto out_fd1; | ||
1236 | } | ||
1237 | |||
1238 | err = audit_fd_pair(fd1, fd2); | ||
1239 | if (err < 0) { | ||
1240 | fput(newfile1); | ||
1241 | fput(newfile2); | ||
1242 | goto out_fd; | ||
1243 | } | ||
1226 | 1244 | ||
1245 | fd_install(fd1, newfile1); | ||
1246 | fd_install(fd2, newfile2); | ||
1227 | /* fd1 and fd2 may be already another descriptors. | 1247 | /* fd1 and fd2 may be already another descriptors. |
1228 | * Not kernel problem. | 1248 | * Not kernel problem. |
1229 | */ | 1249 | */ |
@@ -1238,17 +1258,23 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, | |||
1238 | sys_close(fd1); | 1258 | sys_close(fd1); |
1239 | return err; | 1259 | return err; |
1240 | 1260 | ||
1241 | out_close_1: | ||
1242 | sock_release(sock2); | ||
1243 | sys_close(fd1); | ||
1244 | return err; | ||
1245 | |||
1246 | out_release_both: | 1261 | out_release_both: |
1247 | sock_release(sock2); | 1262 | sock_release(sock2); |
1248 | out_release_1: | 1263 | out_release_1: |
1249 | sock_release(sock1); | 1264 | sock_release(sock1); |
1250 | out: | 1265 | out: |
1251 | return err; | 1266 | return err; |
1267 | |||
1268 | out_fd2: | ||
1269 | put_filp(newfile1); | ||
1270 | sock_release(sock1); | ||
1271 | out_fd1: | ||
1272 | put_filp(newfile2); | ||
1273 | sock_release(sock2); | ||
1274 | out_fd: | ||
1275 | put_unused_fd(fd1); | ||
1276 | put_unused_fd(fd2); | ||
1277 | goto out; | ||
1252 | } | 1278 | } |
1253 | 1279 | ||
1254 | /* | 1280 | /* |