Advertisement
Guest User

Untitled

a guest
Aug 27th, 2016
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.74 KB | None | 0 0
  1. #ifndef FORKMONITOR_H
  2. #define FORKMONITOR_H
  3.  
  4. #define FORKMONITOR_ENVNAME "FORKMONITOR_SOCKET"
  5.  
  6. #ifndef UNIX_PATH_MAX
  7. #define UNIX_PATH_MAX 108
  8. #endif
  9.  
  10. #define TYPE_EXEC 1 /* When a binary is executed */
  11. #define TYPE_DONE 2 /* exit() or return from main() */
  12. #define TYPE_FORK 3
  13. #define TYPE_VFORK 4
  14. #define TYPE_EXIT 5 /* _exit() or _Exit() */
  15. #define TYPE_ABORT 6 /* abort() */
  16.  
  17. struct message {
  18. pid_t pid; /* Process ID */
  19. pid_t ppid; /* Parent process ID */
  20. pid_t sid; /* Session ID */
  21. pid_t pgid; /* Process group ID */
  22. uid_t uid; /* Real user ID */
  23. gid_t gid; /* Real group ID */
  24. uid_t euid; /* Effective user ID */
  25. gid_t egid; /* Effective group ID */
  26. unsigned short len; /* Length of data[] */
  27. unsigned char type; /* One of the TYPE_ constants */
  28. char data[0]; /* Optional payload, possibly longer */
  29. };
  30.  
  31. #endif /* FORKMONITOR_H */
  32.  
  33. #define _POSIX_C_SOURCE 200809L
  34. #define _GNU_SOURCE
  35. #include <stdlib.h>
  36. #include <unistd.h>
  37. #include <sys/types.h>
  38. #include <sys/socket.h>
  39. #include <sys/stat.h>
  40. #include <sys/un.h>
  41. #include <dlfcn.h>
  42. #include <limits.h>
  43. #include <string.h>
  44. #include <stdio.h>
  45. #include <errno.h>
  46. #include "forkmonitor.h"
  47.  
  48. static pid_t (*actual_fork)(void) = NULL;
  49. static pid_t (*actual_vfork)(void) = NULL;
  50. static void (*actual_abort)(void) = NULL;
  51. static void (*actual__exit)(int) = NULL;
  52. static void (*actual__Exit)(int) = NULL;
  53. static int commfd = -1;
  54.  
  55. #define MINIMUM_COMMFD 31
  56.  
  57. static void notify(const int type, struct message *const msg, const size_t extra)
  58. {
  59. const int saved_errno = errno;
  60.  
  61. msg->pid = getpid();
  62. msg->ppid = getppid();
  63. msg->sid = getsid(0);
  64. msg->pgid = getpgrp();
  65. msg->uid = getuid();
  66. msg->gid = getgid();
  67. msg->euid = geteuid();
  68. msg->egid = getegid();
  69. msg->len = extra;
  70. msg->type = type;
  71.  
  72. /* Since we don't have any method of dealing with send() errors
  73. * or partial send()s, we just fire one off and hope for the best. */
  74. send(commfd, msg, sizeof (struct message) + extra, MSG_EOR | MSG_NOSIGNAL);
  75.  
  76. errno = saved_errno;
  77. }
  78.  
  79. void libforkmonitor_init(void) __attribute__((constructor));
  80. void libforkmonitor_init(void)
  81. {
  82. const int saved_errno = errno;
  83. int result;
  84.  
  85. /* Save the actual fork() call pointer. */
  86. if (!actual_fork)
  87. *(void **)&actual_fork = dlsym(RTLD_NEXT, "fork");
  88.  
  89. /* Save the actual vfork() call pointer. */
  90. if (!actual_vfork)
  91. *(void **)&actual_vfork = dlsym(RTLD_NEXT, "vfork");
  92.  
  93. /* Save the actual abort() call pointer. */
  94. if (!actual_abort)
  95. *(void **)&actual_abort = dlsym(RTLD_NEXT, "abort");
  96.  
  97. /* Save the actual _exit() call pointer. */
  98. if (!actual__exit)
  99. *(void **)&actual__exit = dlsym(RTLD_NEXT, "_exit");
  100. if (!actual__exit)
  101. *(void **)&actual__exit = dlsym(RTLD_NEXT, "_Exit");
  102.  
  103. /* Save the actual abort() call pointer. */
  104. if (!actual__Exit)
  105. *(void **)&actual__Exit = dlsym(RTLD_NEXT, "_Exit");
  106. if (!actual__Exit)
  107. *(void **)&actual__Exit = dlsym(RTLD_NEXT, "_exit");
  108.  
  109. /* Open an Unix domain datagram socket to the observer. */
  110. if (commfd == -1) {
  111. const char *address;
  112.  
  113. /* Connect to where? */
  114. address = getenv(FORKMONITOR_ENVNAME);
  115. if (address && *address) {
  116. struct sockaddr_un addr;
  117.  
  118. memset(&addr, 0, sizeof addr);
  119. addr.sun_family = AF_UNIX;
  120. strncpy(addr.sun_path, address, sizeof addr.sun_path - 1);
  121.  
  122. /* Create and bind the socket. */
  123. commfd = socket(AF_UNIX, SOCK_DGRAM, 0);
  124. if (commfd != -1) {
  125. if (connect(commfd, (const struct sockaddr *)&addr, sizeof (addr)) == -1) {
  126. /* Failed. Close the socket. */
  127. do {
  128. result = close(commfd);
  129. } while (result == -1 && errno == EINTR);
  130. commfd = -1;
  131. }
  132. }
  133.  
  134. /* Move commfd to a high descriptor, to avoid complications. */
  135. if (commfd != -1 && commfd < MINIMUM_COMMFD) {
  136. const int newfd = MINIMUM_COMMFD;
  137. do {
  138. result = dup2(commfd, newfd);
  139. } while (result == -1 && errno == EINTR);
  140. if (!result) {
  141. do {
  142. result = close(commfd);
  143. } while (result == -1 && errno == EINTR);
  144. commfd = newfd;
  145. }
  146. }
  147. }
  148. }
  149.  
  150. /* Send an init message, listing the executable path. */
  151. if (commfd != -1) {
  152. size_t len = 128;
  153. struct message *msg = NULL;
  154.  
  155. while (1) {
  156. ssize_t n;
  157.  
  158. free(msg);
  159. msg = malloc(sizeof (struct message) + len);
  160. if (!msg) {
  161. len = 0;
  162. break;
  163. }
  164.  
  165. n = readlink("/proc/self/exe", msg->data, len);
  166. if (n > (ssize_t)0 && (size_t)n < len) {
  167. msg->data[n] = '';
  168. len = n + 1;
  169. break;
  170. }
  171.  
  172. len = (3 * len) / 2;
  173. if (len >= 65536U) {
  174. free(msg);
  175. msg = NULL;
  176. len = 0;
  177. break;
  178. }
  179. }
  180.  
  181. if (len > 0) {
  182. /* INIT message with executable name */
  183. notify(TYPE_EXEC, msg, len);
  184. free(msg);
  185. } else {
  186. /* INIT message without executable name */
  187. struct message msg2;
  188. notify(TYPE_EXEC, &msg2, sizeof msg2);
  189. }
  190. }
  191.  
  192. /* Restore errno. */
  193. errno = saved_errno;
  194. }
  195.  
  196. void libforkmonitor_done(void) __attribute__((destructor));
  197. void libforkmonitor_done(void)
  198. {
  199. const int saved_errno = errno;
  200. int result;
  201.  
  202. /* Send an exit message, no data. */
  203. if (commfd != -1) {
  204. struct message msg;
  205. notify(TYPE_DONE, &msg, sizeof msg);
  206. }
  207.  
  208. /* If commfd is open, close it. */
  209. if (commfd != -1) {
  210. do {
  211. result = close(commfd);
  212. } while (result == -1 && errno == EINTR);
  213. }
  214.  
  215. /* Restore errno. */
  216. errno = saved_errno;
  217. }
  218.  
  219. /*
  220. * Hooked C library functions.
  221. */
  222.  
  223. pid_t fork(void)
  224. {
  225. pid_t result;
  226.  
  227. if (!actual_fork) {
  228. const int saved_errno = errno;
  229.  
  230. *(void **)&actual_fork = dlsym(RTLD_NEXT, "fork");
  231. if (!actual_fork) {
  232. errno = EAGAIN;
  233. return (pid_t)-1;
  234. }
  235.  
  236. errno = saved_errno;
  237. }
  238.  
  239. result = actual_fork();
  240. if (!result && commfd != -1) {
  241. struct message msg;
  242. notify(TYPE_FORK, &msg, sizeof msg);
  243. }
  244.  
  245. return result;
  246. }
  247.  
  248. pid_t vfork(void)
  249. {
  250. pid_t result;
  251.  
  252. if (!actual_vfork) {
  253. const int saved_errno = errno;
  254.  
  255. *(void **)&actual_vfork = dlsym(RTLD_NEXT, "vfork");
  256. if (!actual_vfork) {
  257. errno = EAGAIN;
  258. return (pid_t)-1;
  259. }
  260.  
  261. errno = saved_errno;
  262. }
  263.  
  264. result = actual_vfork();
  265. if (!result && commfd != -1) {
  266. struct message msg;
  267. notify(TYPE_VFORK, &msg, sizeof msg);
  268. }
  269.  
  270. return result;
  271. }
  272.  
  273. void _exit(const int code)
  274. {
  275. if (!actual__exit) {
  276. const int saved_errno = errno;
  277. *(void **)&actual__exit = dlsym(RTLD_NEXT, "_exit");
  278. if (!actual__exit)
  279. *(void **)&actual__exit = dlsym(RTLD_NEXT, "_Exit");
  280. errno = saved_errno;
  281. }
  282.  
  283. if (commfd != -1) {
  284. struct {
  285. struct message msg;
  286. int extra;
  287. } data;
  288.  
  289. memcpy(&data.msg.data[0], &code, sizeof code);
  290. notify(TYPE_EXIT, &(data.msg), sizeof (struct message) + sizeof (int));
  291. }
  292.  
  293. if (actual__exit)
  294. actual__exit(code);
  295.  
  296. exit(code);
  297. }
  298.  
  299. void _Exit(const int code)
  300. {
  301. if (!actual__Exit) {
  302. const int saved_errno = errno;
  303. *(void **)&actual__Exit = dlsym(RTLD_NEXT, "_Exit");
  304. if (!actual__Exit)
  305. *(void **)&actual__Exit = dlsym(RTLD_NEXT, "_exit");
  306. errno = saved_errno;
  307. }
  308.  
  309. if (commfd != -1) {
  310. struct {
  311. struct message msg;
  312. int extra;
  313. } data;
  314.  
  315. memcpy(&data.msg.data[0], &code, sizeof code);
  316. notify(TYPE_EXIT, &(data.msg), sizeof (struct message) + sizeof (int));
  317. }
  318.  
  319. if (actual__Exit)
  320. actual__Exit(code);
  321.  
  322. exit(code);
  323. }
  324.  
  325. void abort(void)
  326. {
  327. if (!actual_abort) {
  328. const int saved_errno = errno;
  329. *(void **)&actual_abort = dlsym(RTLD_NEXT, "abort");
  330. errno = saved_errno;
  331. }
  332.  
  333. if (commfd != -1) {
  334. struct message msg;
  335. notify(TYPE_ABORT, &msg, sizeof msg);
  336. }
  337.  
  338. actual_abort();
  339. exit(127);
  340. }
  341.  
  342. #define _POSIX_C_SOURCE 200809L
  343. #include <unistd.h>
  344. #include <stdlib.h>
  345. #include <sys/socket.h>
  346. #include <sys/un.h>
  347. #include <signal.h>
  348. #include <pwd.h>
  349. #include <grp.h>
  350. #include <string.h>
  351. #include <stdio.h>
  352. #include <errno.h>
  353. #include "forkmonitor.h"
  354.  
  355. static volatile sig_atomic_t done = 0;
  356.  
  357. static void done_handler(const int signum)
  358. {
  359. if (!done)
  360. done = signum;
  361. }
  362.  
  363. static int catch_done(const int signum)
  364. {
  365. struct sigaction act;
  366.  
  367. sigemptyset(&act.sa_mask);
  368. act.sa_handler = done_handler;
  369. act.sa_flags = 0;
  370.  
  371. if (sigaction(signum, &act, NULL) == -1)
  372. return errno;
  373.  
  374. return 0;
  375. }
  376.  
  377. static const char *username(const uid_t uid)
  378. {
  379. static char buffer[128];
  380. struct passwd *pw;
  381.  
  382. pw = getpwuid(uid);
  383. if (!pw)
  384. return NULL;
  385.  
  386. strncpy(buffer, pw->pw_name, sizeof buffer - 1);
  387. buffer[sizeof buffer - 1] = '';
  388.  
  389. return (const char *)buffer;
  390. }
  391.  
  392. static const char *groupname(const gid_t gid)
  393. {
  394. static char buffer[128];
  395. struct group *gr;
  396.  
  397. gr = getgrgid(gid);
  398. if (!gr)
  399. return NULL;
  400.  
  401. strncpy(buffer, gr->gr_name, sizeof buffer - 1);
  402. buffer[sizeof buffer - 1] = '';
  403.  
  404. return (const char *)buffer;
  405. }
  406.  
  407. int main(int argc, char *argv[])
  408. {
  409. const size_t msglen = 65536;
  410. struct message *msg;
  411. int socketfd, result;
  412. const char *user, *group;
  413.  
  414. if (catch_done(SIGINT) || catch_done(SIGQUIT) || catch_done(SIGHUP) ||
  415. catch_done(SIGTERM) || catch_done(SIGPIPE)) {
  416. fprintf(stderr, "Cannot set signal handlers: %s.n", strerror(errno));
  417. return 1;
  418. }
  419.  
  420. if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
  421. fprintf(stderr, "n");
  422. fprintf(stderr, "Usage: %s [ -h | --help ]n", argv[0]);
  423. fprintf(stderr, " %s MONITOR-SOCKET-PATHn", argv[0]);
  424. fprintf(stderr, "n");
  425. fprintf(stderr, "This program outputs events reported by libforkmonitorn");
  426. fprintf(stderr, "to Unix domain datagram sockets at MONITOR-SOCKET-PATH.n");
  427. fprintf(stderr, "n");
  428. return 0;
  429. }
  430.  
  431. msg = malloc(msglen);
  432. if (!msg) {
  433. fprintf(stderr, "Out of memory.n");
  434. return 1;
  435. }
  436.  
  437. socketfd = socket(AF_UNIX, SOCK_DGRAM, 0);
  438. if (socketfd == -1) {
  439. fprintf(stderr, "Cannot create an Unix domain datagram socket: %s.n", strerror(errno));
  440. return 1;
  441. }
  442.  
  443. {
  444. struct sockaddr_un addr;
  445. size_t len;
  446.  
  447. if (argv[1])
  448. len = strlen(argv[1]);
  449. else
  450. len = 0;
  451. if (len < 1 || len >= UNIX_PATH_MAX) {
  452. fprintf(stderr, "%s: Path is too long (max. %d characters)n", argv[1], UNIX_PATH_MAX - 1);
  453. return 1;
  454. }
  455.  
  456. memset(&addr, 0, sizeof addr);
  457. addr.sun_family = AF_UNIX;
  458. memcpy(addr.sun_path, argv[1], len + 1); /* Include '' at end */
  459.  
  460. if (bind(socketfd, (struct sockaddr *)&addr, sizeof (addr)) == -1) {
  461. fprintf(stderr, "Cannot bind to %s: %s.n", argv[1], strerror(errno));
  462. return 1;
  463. }
  464. }
  465.  
  466. printf("Waiting for connections.n");
  467. printf("n");
  468.  
  469. /* Infinite loop. */
  470. while (!done) {
  471. ssize_t n;
  472.  
  473. n = recv(socketfd, msg, msglen, 0);
  474. if (n == -1) {
  475. const char *const errmsg = strerror(errno);
  476. fprintf(stderr, "%s.n", errmsg);
  477. fflush(stderr);
  478. break;
  479. }
  480.  
  481. if (msglen < sizeof (struct message)) {
  482. fprintf(stderr, "Received a partial message; discarded.n");
  483. fflush(stderr);
  484. continue;
  485. }
  486.  
  487. switch (msg->type) {
  488. case TYPE_EXEC:
  489. printf("Received an EXEC message:n");
  490. break;
  491. case TYPE_DONE:
  492. printf("Received a DONE message:n");
  493. break;
  494. case TYPE_FORK:
  495. printf("Received a FORK message:n");
  496. break;
  497. case TYPE_VFORK:
  498. printf("Received a VFORK message:n");
  499. break;
  500. case TYPE_EXIT:
  501. printf("Received an EXIT message:n");
  502. break;
  503. case TYPE_ABORT:
  504. printf("Received an ABORT message:n");
  505. break;
  506. default:
  507. printf("Received an UNKNOWN message:n");
  508. break;
  509. }
  510.  
  511. if (msg->type == TYPE_EXEC && (size_t)n > sizeof (struct message)) {
  512. if (*((char *)msg + n - 1) == '')
  513. printf("tExecutable: '%s'n", (char *)msg + sizeof (struct message));
  514. }
  515.  
  516. printf("tProcess ID: %dn", (int)msg->pid);
  517. printf("tParent process ID: %dn", (int)msg->ppid);
  518. printf("tSession ID: %dn", (int)msg->sid);
  519. printf("tProcess group ID: %dn", (int)msg->pgid);
  520.  
  521. user = username(msg->uid);
  522. if (user)
  523. printf("tReal user: '%s' (%d)n", user, (int)msg->uid);
  524. else
  525. printf("tReal user: %dn", (int)msg->uid);
  526.  
  527. group = groupname(msg->gid);
  528. if (group)
  529. printf("tReal group: '%s' (%d)n", group, (int)msg->gid);
  530. else
  531. printf("tReal group: %dn", (int)msg->gid);
  532.  
  533. user = username(msg->euid);
  534. if (user)
  535. printf("tEffective user: '%s' (%d)n", user, (int)msg->euid);
  536. else
  537. printf("tEffective user: %dn", (int)msg->euid);
  538.  
  539. group = groupname(msg->egid);
  540. if (group)
  541. printf("tEffective group: '%s' (%d)n", group, (int)msg->egid);
  542. else
  543. printf("tEffective group: %dn", (int)msg->egid);
  544.  
  545. printf("n");
  546. fflush(stdout);
  547. }
  548.  
  549. do {
  550. result = close(socketfd);
  551. } while (result == -1 && errno == EINTR);
  552.  
  553. unlink(argv[1]);
  554.  
  555. return 0;
  556. }
  557.  
  558. gcc -W -Wall -O3 -fpic -fPIC -c libforkmonitor.c
  559. gcc -shared -Wl,-soname,libforkmonitor.so libforkmonitor.o -ldl -o libforkmonitor.so
  560.  
  561. gcc -W -Wall -O3 forkmonitor.c -o forkmonitor
  562.  
  563. ./forkmonitor "$PWD/commsocket"
  564.  
  565. env "LD_PRELOAD=$PWD/libforkmonitor.so" "FORKMONITOR_SOCKET=$PWD/commsocket" command args...
  566.  
  567. env "LD_PRELOAD=$PWD/libforkmonitor.so" "FORKMONITOR_SOCKET=$PWD/commsocket" sh -c 'date ; ls -laF'
  568.  
  569. Received an EXEC message:
  570. Executable: 'bin/dash'
  571. Process ID: 11403
  572. Parent process ID: 9265
  573. Session ID: 9265
  574. Process group ID: 11403
  575. Real user: 'username' (1000)
  576. Real group: 'username' (1000)
  577. Effective user: 'username' (1000)
  578. Effective group: 'username' (1000)
  579.  
  580. Received a FORK message:
  581. Process ID: 11404
  582. Parent process ID: 11403
  583. Session ID: 9265
  584. Process group ID: 11403
  585. Real user: 'username' (1000)
  586. Real group: 'username' (1000)
  587. Effective user: 'username' (1000)
  588. Effective group: 'username' (1000)
  589.  
  590. Received an EXEC message:
  591. Executable: 'bin/date'
  592. Process ID: 11404
  593. Parent process ID: 11403
  594. Session ID: 9265
  595. Process group ID: 11403
  596. Real user: 'username' (1000)
  597. Real group: 'username' (1000)
  598. Effective user: 'username' (1000)
  599. Effective group: 'username' (1000)
  600.  
  601. Received a DONE message:
  602. Process ID: 11404
  603. Parent process ID: 11403
  604. Session ID: 9265
  605. Process group ID: 11403
  606. Real user: 'username' (1000)
  607. Real group: 'username' (1000)
  608. Effective user: 'username' (1000)
  609. Effective group: 'username' (1000)
  610.  
  611. Received a FORK message:
  612. Process ID: 11405
  613. Parent process ID: 11403
  614. Session ID: 9265
  615. Process group ID: 11403
  616. Real user: 'username' (1000)
  617. Real group: 'username' (1000)
  618. Effective user: 'username' (1000)
  619. Effective group: 'username' (1000)
  620.  
  621. Received an EXEC message:
  622. Executable: 'bin/ls'
  623. Process ID: 11405
  624. Parent process ID: 11403
  625. Session ID: 9265
  626. Process group ID: 11403
  627. Real user: 'username' (1000)
  628. Real group: 'username' (1000)
  629. Effective user: 'username' (1000)
  630. Effective group: 'username' (1000)
  631.  
  632. Received a DONE message:
  633. Process ID: 11405
  634. Parent process ID: 11403
  635. Session ID: 9265
  636. Process group ID: 11403
  637. Real user: 'username' (1000)
  638. Real group: 'username' (1000)
  639. Effective user: 'username' (1000)
  640. Effective group: 'username' (1000)
  641.  
  642. Received an EXIT message:
  643. Process ID: 11403
  644. Parent process ID: 9265
  645. Session ID: 9265
  646. Process group ID: 11403
  647. Real user: 'username' (1000)
  648. Real group: 'username' (1000)
  649. Effective user: 'username' (1000)
  650. Effective group: 'username' (1000)
  651.  
  652. [root@hip1 yotest]# ./proc
  653. set mcast listen ok
  654. fork: parent tid=2358 pid=2358 -> child tid=21007 pid=21007
  655. exec: tid=21007 pid=21007
  656. fork: parent tid=21007 pid=21007 -> child tid=21008 pid=21008
  657. fork: parent tid=21007 pid=21007 -> child tid=21009 pid=21009
  658. fork: parent tid=21007 pid=21007 -> child tid=21010 pid=21010
  659. fork: parent tid=21007 pid=21007 -> child tid=21011 pid=21011
  660. exec: tid=21010 pid=21010
  661. exec: tid=21008 pid=21008
  662. exec: tid=21011 pid=21011
  663. exec: tid=21009 pid=21009
  664. exit: tid=21008 pid=21008 exit_code=0
  665. fork: parent tid=21010 pid=21010 -> child tid=21012 pid=21012
  666. exit: tid=21009 pid=21009 exit_code=0
  667. exec: tid=21012 pid=21012
  668. exit: tid=21012 pid=21012 exit_code=0
  669. exit: tid=21010 pid=21010 exit_code=0
  670. exit: tid=21011 pid=21011 exit_code=0
  671. exit: tid=21007 pid=21007 exit_code=0
  672.  
  673. #include <sys/socket.h>
  674. #include <linux/netlink.h>
  675. #include <linux/connector.h>
  676. #include <linux/cn_proc.h>
  677. #include <signal.h>
  678. #include <errno.h>
  679. #include <stdbool.h>
  680. #include <unistd.h>
  681. #include <string.h>
  682. #include <stdlib.h>
  683. #include <stdio.h>
  684.  
  685. /*
  686. * connect to netlink
  687. * returns netlink socket, or -1 on error
  688. */
  689. static int nl_connect()
  690. {
  691. int rc;
  692. int nl_sock;
  693. struct sockaddr_nl sa_nl;
  694.  
  695. nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
  696. if (nl_sock == -1) {
  697. perror("socket");
  698. return -1;
  699. }
  700.  
  701. sa_nl.nl_family = AF_NETLINK;
  702. sa_nl.nl_groups = CN_IDX_PROC;
  703. sa_nl.nl_pid = getpid();
  704.  
  705. rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
  706. if (rc == -1) {
  707. perror("bind");
  708. close(nl_sock);
  709. return -1;
  710. }
  711.  
  712. return nl_sock;
  713. }
  714.  
  715. /*
  716. * subscribe on proc events (process notifications)
  717. */
  718. static int set_proc_ev_listen(int nl_sock, bool enable)
  719. {
  720. int rc;
  721. struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
  722. struct nlmsghdr nl_hdr;
  723. struct __attribute__ ((__packed__)) {
  724. struct cn_msg cn_msg;
  725. enum proc_cn_mcast_op cn_mcast;
  726. };
  727. } nlcn_msg;
  728.  
  729. memset(&nlcn_msg, 0, sizeof(nlcn_msg));
  730. nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg);
  731. nlcn_msg.nl_hdr.nlmsg_pid = getpid();
  732. nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE;
  733.  
  734. nlcn_msg.cn_msg.id.idx = CN_IDX_PROC;
  735. nlcn_msg.cn_msg.id.val = CN_VAL_PROC;
  736. nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);
  737.  
  738. nlcn_msg.cn_mcast = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE;
  739.  
  740. rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
  741. if (rc == -1) {
  742. perror("netlink send");
  743. return -1;
  744. }
  745.  
  746. return 0;
  747. }
  748.  
  749. /*
  750. * handle a single process event
  751. */
  752. static volatile bool need_exit = false;
  753. static int handle_proc_ev(int nl_sock)
  754. {
  755. int rc;
  756. struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
  757. struct nlmsghdr nl_hdr;
  758. struct __attribute__ ((__packed__)) {
  759. struct cn_msg cn_msg;
  760. struct proc_event proc_ev;
  761. };
  762. } nlcn_msg;
  763.  
  764. while (!need_exit) {
  765. rc = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
  766. if (rc == 0) {
  767. /* shutdown? */
  768. return 0;
  769. } else if (rc == -1) {
  770. if (errno == EINTR) continue;
  771. perror("netlink recv");
  772. return -1;
  773. }
  774. switch (nlcn_msg.proc_ev.what) {
  775. case PROC_EVENT_NONE:
  776. printf("set mcast listen okn");
  777. break;
  778. case PROC_EVENT_FORK:
  779. printf("fork: parent tid=%d pid=%d -> child tid=%d pid=%dn",
  780. nlcn_msg.proc_ev.event_data.fork.parent_pid,
  781. nlcn_msg.proc_ev.event_data.fork.parent_tgid,
  782. nlcn_msg.proc_ev.event_data.fork.child_pid,
  783. nlcn_msg.proc_ev.event_data.fork.child_tgid);
  784. break;
  785. case PROC_EVENT_EXEC:
  786. printf("exec: tid=%d pid=%dn",
  787. nlcn_msg.proc_ev.event_data.exec.process_pid,
  788. nlcn_msg.proc_ev.event_data.exec.process_tgid);
  789. break;
  790. case PROC_EVENT_UID:
  791. printf("uid change: tid=%d pid=%d from %d to %dn",
  792. nlcn_msg.proc_ev.event_data.id.process_pid,
  793. nlcn_msg.proc_ev.event_data.id.process_tgid,
  794. nlcn_msg.proc_ev.event_data.id.r.ruid,
  795. nlcn_msg.proc_ev.event_data.id.e.euid);
  796. break;
  797. case PROC_EVENT_GID:
  798. printf("gid change: tid=%d pid=%d from %d to %dn",
  799. nlcn_msg.proc_ev.event_data.id.process_pid,
  800. nlcn_msg.proc_ev.event_data.id.process_tgid,
  801. nlcn_msg.proc_ev.event_data.id.r.rgid,
  802. nlcn_msg.proc_ev.event_data.id.e.egid);
  803. break;
  804. case PROC_EVENT_EXIT:
  805. printf("exit: tid=%d pid=%d exit_code=%dn",
  806. nlcn_msg.proc_ev.event_data.exit.process_pid,
  807. nlcn_msg.proc_ev.event_data.exit.process_tgid,
  808. nlcn_msg.proc_ev.event_data.exit.exit_code);
  809. break;
  810. default:
  811. printf("unhandled proc eventn");
  812. break;
  813. }
  814. }
  815.  
  816. return 0;
  817. }
  818.  
  819. static void on_sigint(int unused)
  820. {
  821. need_exit = true;
  822. }
  823.  
  824. int main(int argc, const char *argv[])
  825. {
  826. int nl_sock;
  827. int rc = EXIT_SUCCESS;
  828.  
  829. signal(SIGINT, &on_sigint);
  830. siginterrupt(SIGINT, true);
  831.  
  832. nl_sock = nl_connect();
  833. if (nl_sock == -1)
  834. exit(EXIT_FAILURE);
  835.  
  836. rc = set_proc_ev_listen(nl_sock, true);
  837. if (rc == -1) {
  838. rc = EXIT_FAILURE;
  839. goto out;
  840. }
  841.  
  842. rc = handle_proc_ev(nl_sock);
  843. if (rc == -1) {
  844. rc = EXIT_FAILURE;
  845. goto out;
  846. }
  847.  
  848. set_proc_ev_listen(nl_sock, false);
  849.  
  850. out:
  851. close(nl_sock);
  852. exit(rc);
  853. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement