PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/auditd/libaudit.c

https://gitlab.com/infraredbg/android_system_core-mt6589
C | 488 lines | 295 code | 71 blank | 122 comment | 80 complexity | 2505f7758e377754b7a108772c0bcaa3 MD5 | raw file
  1. /*
  2. * Copyright 2012, Samsung Telecommunications of America
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. * Written by William Roberts <w.roberts@sta.samsung.com>
  17. *
  18. */
  19. #include <errno.h>
  20. #include <fcntl.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <stdint.h>
  24. #include <stdlib.h>
  25. #include <sys/types.h>
  26. #include <pwd.h>
  27. #include <grp.h>
  28. #include <ctype.h>
  29. #define LOG_TAG "libaudit"
  30. #include <cutils/log.h>
  31. #include <cutils/klog.h>
  32. #include "libaudit.h"
  33. #include "fields.h"
  34. /**
  35. * Copies the netlink message data to the reply structure.
  36. *
  37. * When the kernel sends a response back, we must adjust the response from the
  38. * netlink message header.
  39. * All the data is in rep->msg but belongs in the type enforced fields in the struct.
  40. *
  41. * @param rep
  42. * The response
  43. * @param len
  44. * The length of the message, len must never be less than 0!
  45. * @return
  46. * This function returns 0 on success, else -error.
  47. */
  48. static int set_internal_fields(struct audit_reply *rep, ssize_t len)
  49. {
  50. int rc;
  51. /*
  52. * We end up setting a specific field in the union, but since it
  53. * is a union and they are all of type pointer, we can just clear
  54. * one.
  55. */
  56. rep->status = NULL;
  57. /* Set the response from the netlink message */
  58. rep->nlh = &rep->msg.nlh;
  59. rep->len = rep->msg.nlh.nlmsg_len;
  60. rep->type = rep->msg.nlh.nlmsg_type;
  61. /* Check if the reply from the kernel was ok */
  62. if (!NLMSG_OK(rep->nlh, (size_t)len)) {
  63. rc = (len == sizeof(rep->msg)) ? -EFBIG : -EBADE;
  64. SLOGE("Bad kernel response %s", strerror(-rc));
  65. return rc;
  66. }
  67. /* Next we'll set the data structure to point to msg.data. This is
  68. * to avoid having to use casts later. */
  69. if (rep->type == NLMSG_ERROR) {
  70. rep->error = NLMSG_DATA(rep->nlh);
  71. } else if (rep->type == AUDIT_GET) {
  72. rep->status = NLMSG_DATA(rep->nlh);
  73. } else if (rep->type == AUDIT_LIST_RULES) {
  74. rep->ruledata = NLMSG_DATA(rep->nlh);
  75. } else if (rep->type == AUDIT_SIGNAL_INFO) {
  76. rep->signal_info = NLMSG_DATA(rep->nlh);
  77. }
  78. /* If it is not any of the above specific events, it must be a generic message */
  79. else {
  80. rep->message = NLMSG_DATA(rep->nlh);
  81. }
  82. return 0;
  83. }
  84. /**
  85. * Waits for an ack from the kernel
  86. * @param fd
  87. * The netlink socket fd
  88. * @param seq
  89. * The current sequence number were acking on
  90. * @return
  91. * This function returns 0 on success, else -errno.
  92. */
  93. static int get_ack(int fd, int16_t seq)
  94. {
  95. int rc;
  96. struct audit_reply rep;
  97. /* Sanity check the input, this is an internal interface this shouldn't happen */
  98. if (fd < 0) {
  99. return -EINVAL;
  100. }
  101. rc = audit_get_reply(fd, &rep, GET_REPLY_BLOCKING, MSG_PEEK);
  102. if (rc < 0) {
  103. return rc;
  104. }
  105. if (rep.type == NLMSG_ERROR) {
  106. audit_get_reply(fd, &rep, GET_REPLY_BLOCKING, 0);
  107. if (rep.error->error) {
  108. return -rep.error->error;
  109. }
  110. }
  111. if ((int16_t)rep.nlh->nlmsg_seq != seq) {
  112. SLOGW("Expected sequence number between user space and kernel space is out of skew, "
  113. "expected %u got %u", seq, rep.nlh->nlmsg_seq);
  114. }
  115. return 0;
  116. }
  117. /**
  118. *
  119. * @param fd
  120. * The netlink socket fd
  121. * @param type
  122. * The type of netlink message
  123. * @param data
  124. * The data to send
  125. * @param size
  126. * The length of the data in bytes
  127. * @return
  128. * This function returns a positive sequence number on success, else -errno.
  129. */
  130. int audit_send(int fd, int type, const void *data, unsigned int size)
  131. {
  132. int rc;
  133. static int16_t sequence = 0;
  134. struct audit_message req;
  135. struct sockaddr_nl addr;
  136. memset(&req, 0, sizeof(req));
  137. memset(&addr, 0, sizeof(addr));
  138. /* We always send netlink messaged */
  139. addr.nl_family = AF_NETLINK;
  140. /* Set up the netlink headers */
  141. req.nlh.nlmsg_type = type;
  142. req.nlh.nlmsg_len = NLMSG_SPACE(size);
  143. req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
  144. /*
  145. * Check for a valid fd, even though sendto would catch this, its easier to always
  146. * blindly increment the sequence number
  147. */
  148. if (fd < 0) {
  149. return -EBADF;
  150. }
  151. /* Ensure the message is not too big */
  152. if (NLMSG_SPACE(size) > MAX_AUDIT_MESSAGE_LENGTH) {
  153. SLOGE("netlink message is too large");
  154. return -EINVAL;
  155. }
  156. /* Only memcpy in the data if it was specified */
  157. if (size && data)
  158. memcpy(NLMSG_DATA(&req.nlh), data, size);
  159. /*
  160. * Only increment the sequence number on a guarantee
  161. * you will send it to the kernel.
  162. *
  163. * Also, the sequence is defined as a u32 in the kernel
  164. * struct. Using an int here might not work on 32/64 bit splits. A
  165. * signed 64 bit value can overflow a u32..but a u32
  166. * might not fit in the response, so we need to use s32.
  167. * Which is still kind of hackish since int could be 16 bits
  168. * in size. The only safe type to use here is a signed 16
  169. * bit value.
  170. */
  171. req.nlh.nlmsg_seq = ++sequence;
  172. /* While failing and its due to interrupts */
  173. do {
  174. /* Try and send the netlink message */
  175. rc = sendto(fd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr*) &addr, sizeof(addr));
  176. } while (rc < 0 && errno == EINTR);
  177. /* Not all the bytes were sent */
  178. if ((uint32_t) rc != req.nlh.nlmsg_len) {
  179. rc = -EPROTO;
  180. goto out;
  181. } else if (rc < 0) {
  182. rc = -errno;
  183. SLOGE("Error sending data over the netlink socket: %s", strerror(-errno));
  184. goto out;
  185. }
  186. /* We sent all the bytes, get the ack */
  187. rc = get_ack(fd, sequence);
  188. /* If the ack failed, return the error, else return the sequence number */
  189. rc = (rc == 0) ? (int) sequence : rc;
  190. out:
  191. /* Don't let sequence roll to negative */
  192. if (sequence < 0) {
  193. SLOGW("Auditd to Kernel sequence number has rolled over");
  194. sequence = 0;
  195. }
  196. return rc;
  197. }
  198. int audit_update_watch_perms(struct audit_rule_data *rule, int perms)
  199. {
  200. uint32_t i;
  201. if (rule == NULL) {
  202. return -EINVAL;
  203. }
  204. for (i = 0; i < rule->field_count; i++) {
  205. if (rule->fields[i] == AUDIT_PERM) {
  206. rule->values[i] = perms;
  207. break;
  208. }
  209. }
  210. if (rule->fields[i] == AUDIT_PERM) {
  211. return 0;
  212. }
  213. if (rule->field_count > AUDIT_MAX_FIELDS - 1) {
  214. return -2;
  215. }
  216. rule->fields[rule->field_count] = AUDIT_PERM;
  217. rule->fieldflags[rule->field_count] = AUDIT_EQUAL;
  218. rule->values[rule->field_count] = perms;
  219. rule->field_count++;
  220. return 0;
  221. }
  222. int audit_add_field(struct audit_rule_data *rule, int field, int oper, char *value)
  223. {
  224. int i;
  225. struct passwd *pw;
  226. struct group *gr;
  227. if (rule == NULL) {
  228. return -EINVAL;
  229. }
  230. if (rule->field_count > AUDIT_MAX_FIELDS - 1) {
  231. return -2;
  232. }
  233. rule->fields[rule->field_count] = field;
  234. rule->fieldflags[rule->field_count] = oper;
  235. switch(field) {
  236. case AUDIT_UID:
  237. case AUDIT_EUID:
  238. case AUDIT_SUID:
  239. case AUDIT_FSUID:
  240. case AUDIT_LOGINUID:
  241. if (isdigit(value[0])) {
  242. rule->values[rule->field_count] = strtoul(value, NULL, 0);
  243. } else {
  244. pw = getpwnam(value);
  245. if (pw == NULL) {
  246. SLOGE("Unknown user %s", value);
  247. return -1;
  248. }
  249. rule->values[rule->field_count] = pw->pw_uid;
  250. }
  251. break;
  252. case AUDIT_GID:
  253. case AUDIT_EGID:
  254. case AUDIT_SGID:
  255. case AUDIT_FSGID:
  256. if (isdigit(value[0])) {
  257. rule->values[rule->field_count] = strtoul(value, NULL, 0);
  258. } else {
  259. gr = getgrnam(value);
  260. if (gr == NULL) {
  261. SLOGE("Unknown group %s", value);
  262. return -1;
  263. }
  264. rule->values[rule->field_count] = gr->gr_gid;
  265. }
  266. break;
  267. case AUDIT_SUCCESS:
  268. // According to the auditctl man page success should only have 0 or 1
  269. if (strcmp(value, "0") == 0 || strcmp(value, "1") == 0) {
  270. rule->values[rule->field_count] = strtoul(value, NULL, 0);
  271. } else {
  272. SLOGE("Invalid value %s for success field", value);
  273. return -1;
  274. }
  275. break;
  276. default:
  277. SLOGE("Unsupported field: %s", audit_field_to_string(field));
  278. return -1;
  279. }
  280. rule->field_count++;
  281. return 0;
  282. }
  283. int audit_add_dir(struct audit_rule_data **rulep, const char *path)
  284. {
  285. int len = strlen(path);
  286. struct audit_rule_data *rule;
  287. if (rulep == NULL) {
  288. return -EINVAL;
  289. }
  290. *rulep = calloc(1, sizeof(*rule) + len);
  291. rule = *rulep;
  292. if (!rule) {
  293. SLOGE("Out of memory");
  294. return -1;
  295. }
  296. rule->flags = AUDIT_FILTER_EXIT;
  297. rule->action = AUDIT_ALWAYS;
  298. rule->field_count = 2;
  299. rule->mask[0] = ~0;
  300. rule->fields[0] = AUDIT_DIR;
  301. rule->fieldflags[0] = AUDIT_EQUAL;
  302. rule->values[0] = len;
  303. rule->mask[1] = ~0;
  304. rule->fields[1] = AUDIT_PERM;
  305. rule->fieldflags[1] = AUDIT_EQUAL;
  306. rule->values[1] = AUDIT_PERM_READ | AUDIT_PERM_WRITE |
  307. AUDIT_PERM_EXEC | AUDIT_PERM_ATTR;
  308. rule->buflen = len;
  309. memcpy(&rule->buf[0], path, len);
  310. return 0;
  311. }
  312. int audit_set_enabled(int fd, uint32_t state)
  313. {
  314. if (state > AUDIT_LOCKED) {
  315. return -1;
  316. }
  317. struct audit_status s;
  318. memset(&s, 0, sizeof(s));
  319. s.mask = AUDIT_STATUS_ENABLED;
  320. s.enabled = state;
  321. return audit_send(fd, AUDIT_SET, &s, sizeof(s));
  322. }
  323. int audit_set_pid(int fd, uint32_t pid, rep_wait_t wmode)
  324. {
  325. int rc;
  326. struct audit_reply rep;
  327. struct audit_status status;
  328. memset(&status, 0, sizeof(status));
  329. /*
  330. * In order to set the auditd PID we send an audit message over the netlink socket
  331. * with the pid field of the status struct set to our current pid, and the
  332. * the mask set to AUDIT_STATUS_PID
  333. */
  334. status.pid = pid;
  335. status.mask = AUDIT_STATUS_PID;
  336. /* Let the kernel know this pid will be registering for audit events */
  337. rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
  338. if (rc < 0) {
  339. SLOGE("Could net set pid for audit events, error: %s", strerror(-rc));
  340. return rc;
  341. }
  342. /*
  343. * In a request where we need to wait for a response, wait for the message
  344. * and discard it. This message confirms and sync's us with the kernel.
  345. * This daemon is now registered as the audit logger. Only wait if the
  346. * wmode is != WAIT_NO
  347. */
  348. if (wmode != WAIT_NO) {
  349. /* TODO
  350. * If the daemon dies and restarts the message didn't come back,
  351. * so I went to non-blocking and it seemed to fix the bug.
  352. * Need to investigate further.
  353. */
  354. audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0);
  355. }
  356. return 0;
  357. }
  358. int audit_open()
  359. {
  360. return socket(PF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
  361. }
  362. int audit_get_reply(int fd, struct audit_reply *rep, reply_t block, int peek)
  363. {
  364. ssize_t len;
  365. int flags;
  366. struct sockaddr_nl nladdr;
  367. socklen_t nladdrlen = sizeof(nladdr);
  368. if (fd < 0) {
  369. return -EBADF;
  370. }
  371. /* Set up the flags for recv from */
  372. flags = (block == GET_REPLY_NONBLOCKING) ? MSG_DONTWAIT : 0;
  373. flags |= peek;
  374. /*
  375. * Get the data from the netlink socket but on error we need to be carefull,
  376. * the interface shows that EINTR can never be returned, other errors, however,
  377. * can be returned.
  378. */
  379. do {
  380. len = recvfrom(fd, &rep->msg, sizeof(rep->msg), flags, (struct sockaddr*) &nladdr,
  381. &nladdrlen);
  382. /*
  383. * EAGAIN and EINTR should be re-tried until success or
  384. * another error manifests.
  385. */
  386. if (len < 0 && errno != EINTR) {
  387. if (errno == EAGAIN) {
  388. if (block == GET_REPLY_NONBLOCKING) {
  389. /* If the request is non blocking and the errno is EAGAIN, just return 0 */
  390. return 0;
  391. }
  392. } else {
  393. SLOGE("Error receiving from netlink socket, error: %s", strerror(errno));
  394. return -errno;
  395. }
  396. }
  397. /* 0 or greater indicates success */
  398. } while (len < 0);
  399. if (nladdrlen != sizeof(nladdr)) {
  400. SLOGE("Protocol fault, error: %s", strerror(EPROTO));
  401. return -EPROTO;
  402. }
  403. /* Make sure the netlink message was not spoof'd */
  404. if (nladdr.nl_pid) {
  405. SLOGE("Invalid netlink pid received, expected 0 got: %d", nladdr.nl_pid);
  406. return -EINVAL;
  407. }
  408. return set_internal_fields(rep, len);
  409. }
  410. void audit_close(int fd)
  411. {
  412. int rc = close(fd);
  413. if (rc < 0) {
  414. SLOGE("Attempting to close invalid fd %d, error: %s", fd, strerror(errno));
  415. }
  416. return;
  417. }