Commit db3495099d3d52854b13874905af6e40a91f4721
1 parent
6a01b07fae
Exists in
master
and in
39 other branches
[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>
Showing 4 changed files with 95 additions and 13 deletions Side-by-side Diff
fs/pipe.c
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | #include <linux/uio.h> |
17 | 17 | #include <linux/highmem.h> |
18 | 18 | #include <linux/pagemap.h> |
19 | +#include <linux/audit.h> | |
19 | 20 | |
20 | 21 | #include <asm/uaccess.h> |
21 | 22 | #include <asm/ioctls.h> |
... | ... | @@ -985,6 +986,10 @@ |
985 | 986 | goto err_fdr; |
986 | 987 | fdw = error; |
987 | 988 | |
989 | + error = audit_fd_pair(fdr, fdw); | |
990 | + if (error < 0) | |
991 | + goto err_fdw; | |
992 | + | |
988 | 993 | fd_install(fdr, fr); |
989 | 994 | fd_install(fdw, fw); |
990 | 995 | fd[0] = fdr; |
... | ... | @@ -992,6 +997,8 @@ |
992 | 997 | |
993 | 998 | return 0; |
994 | 999 | |
1000 | + err_fdw: | |
1001 | + put_unused_fd(fdw); | |
995 | 1002 | err_fdr: |
996 | 1003 | put_unused_fd(fdr); |
997 | 1004 | err_read_pipe: |
include/linux/audit.h
... | ... | @@ -89,6 +89,7 @@ |
89 | 89 | #define AUDIT_MQ_NOTIFY 1314 /* POSIX MQ notify record type */ |
90 | 90 | #define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */ |
91 | 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 | 94 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
94 | 95 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
... | ... | @@ -387,6 +388,7 @@ |
387 | 388 | extern int audit_bprm(struct linux_binprm *bprm); |
388 | 389 | extern int audit_socketcall(int nargs, unsigned long *args); |
389 | 390 | extern int audit_sockaddr(int len, void *addr); |
391 | +extern int __audit_fd_pair(int fd1, int fd2); | |
390 | 392 | extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); |
391 | 393 | extern int audit_set_macxattr(const char *name); |
392 | 394 | extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr); |
... | ... | @@ -401,6 +403,12 @@ |
401 | 403 | return __audit_ipc_obj(ipcp); |
402 | 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 | 412 | static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) |
405 | 413 | { |
406 | 414 | if (unlikely(!audit_dummy_context())) |
... | ... | @@ -459,6 +467,7 @@ |
459 | 467 | #define audit_ipc_set_perm(q,u,g,m) ({ 0; }) |
460 | 468 | #define audit_bprm(p) ({ 0; }) |
461 | 469 | #define audit_socketcall(n,a) ({ 0; }) |
470 | +#define audit_fd_pair(n,a) ({ 0; }) | |
462 | 471 | #define audit_sockaddr(len, addr) ({ 0; }) |
463 | 472 | #define audit_avc_path(dentry, mnt) ({ 0; }) |
464 | 473 | #define audit_set_macxattr(n) do { ; } while (0) |
kernel/auditsc.c
... | ... | @@ -170,6 +170,11 @@ |
170 | 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 | 178 | struct audit_aux_data_path { |
174 | 179 | struct audit_aux_data d; |
175 | 180 | struct dentry *dentry; |
... | ... | @@ -961,6 +966,11 @@ |
961 | 966 | audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); |
962 | 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 | 975 | audit_log_end(ab); |
966 | 976 | } |
... | ... | @@ -1809,6 +1819,36 @@ |
1809 | 1819 | memcpy(ax->args, args, nargs * sizeof(unsigned long)); |
1810 | 1820 | |
1811 | 1821 | ax->d.type = AUDIT_SOCKETCALL; |
1822 | + ax->d.next = context->aux; | |
1823 | + context->aux = (void *)ax; | |
1824 | + return 0; | |
1825 | +} | |
1826 | + | |
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; | |
1812 | 1852 | ax->d.next = context->aux; |
1813 | 1853 | context->aux = (void *)ax; |
1814 | 1854 | return 0; |
net/socket.c
... | ... | @@ -1194,6 +1194,7 @@ |
1194 | 1194 | { |
1195 | 1195 | struct socket *sock1, *sock2; |
1196 | 1196 | int fd1, fd2, err; |
1197 | + struct file *newfile1, *newfile2; | |
1197 | 1198 | |
1198 | 1199 | /* |
1199 | 1200 | * Obtain the first socket and check if the underlying protocol |
1200 | 1201 | |
1201 | 1202 | |
1202 | 1203 | |
1203 | 1204 | |
... | ... | @@ -1212,18 +1213,37 @@ |
1212 | 1213 | if (err < 0) |
1213 | 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); | |
1218 | - if (err < 0) | |
1220 | + fd2 = sock_alloc_fd(&newfile2); | |
1221 | + if (unlikely(fd2 < 0)) { | |
1222 | + put_filp(newfile1); | |
1223 | + put_unused_fd(fd1); | |
1219 | 1224 | goto out_release_both; |
1220 | - fd1 = err; | |
1225 | + } | |
1221 | 1226 | |
1222 | - err = sock_map_fd(sock2); | |
1223 | - if (err < 0) | |
1224 | - goto out_close_1; | |
1225 | - fd2 = err; | |
1227 | + err = sock_attach_fd(sock1, newfile1); | |
1228 | + if (unlikely(err < 0)) { | |
1229 | + goto out_fd2; | |
1230 | + } | |
1226 | 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 | + } | |
1244 | + | |
1245 | + fd_install(fd1, newfile1); | |
1246 | + fd_install(fd2, newfile2); | |
1227 | 1247 | /* fd1 and fd2 may be already another descriptors. |
1228 | 1248 | * Not kernel problem. |
1229 | 1249 | */ |
1230 | 1250 | |
... | ... | @@ -1238,17 +1258,23 @@ |
1238 | 1258 | sys_close(fd1); |
1239 | 1259 | return err; |
1240 | 1260 | |
1241 | -out_close_1: | |
1242 | - sock_release(sock2); | |
1243 | - sys_close(fd1); | |
1244 | - return err; | |
1245 | - | |
1246 | 1261 | out_release_both: |
1247 | 1262 | sock_release(sock2); |
1248 | 1263 | out_release_1: |
1249 | 1264 | sock_release(sock1); |
1250 | 1265 | out: |
1251 | 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 | /* |