Add libaudit support for adding directory watch rules. Add rule parsing support to auditd.
Rule format matches auditctl. Currently only supports -w and -e. Change-Id: I8bdaea1b5e2a216eec79cd8c9dae583de8295d26 Signed-off-by: Joshua Brindle <[email protected]> --- auditd/Android.mk | 3 +- auditd/audit_log.c | 2 +- auditd/audit_rules.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++ auditd/audit_rules.h | 24 +++++++++ auditd/auditd.c | 7 +++ auditd/libaudit.c | 75 +++++++++++++++++++++++++- auditd/libaudit.h | 52 ++++++++++++++++++ 7 files changed, 305 insertions(+), 3 deletions(-) create mode 100644 auditd/audit_rules.c create mode 100644 auditd/audit_rules.h diff --git a/auditd/Android.mk b/auditd/Android.mk index c29319a..a53b72f 100644 --- a/auditd/Android.mk +++ b/auditd/Android.mk @@ -11,7 +11,8 @@ AUDITD_MAX_LOG_FILE_SIZEKB ?= 100 LOCAL_SRC_FILES:= \ auditd.c \ libaudit.c \ - audit_log.c + audit_log.c \ + audit_rules.c LOCAL_SHARED_LIBRARIES := \ libcutils \ diff --git a/auditd/audit_log.c b/auditd/audit_log.c index ef77a3f..fc50caf 100644 --- a/auditd/audit_log.c +++ b/auditd/audit_log.c @@ -44,7 +44,7 @@ /* Mode for fopen */ #define AUDIT_LOG_FMODE "w+" /* mode for fchmod*/ -#define AUDIT_LOG_MODE (S_IRUSR | S_IWUSR | S_IRGRP) +#define AUDIT_LOG_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) /* flags for fcntl */ #define AUDIT_LOG_FLAGS (O_RDWR | O_CREAT | O_SYNC) diff --git a/auditd/audit_rules.c b/auditd/audit_rules.c new file mode 100644 index 0000000..9e132a9 --- /dev/null +++ b/auditd/audit_rules.c @@ -0,0 +1,145 @@ +/* + * Copyright 2013, Quark Security Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Written by Joshua Brindle <[email protected]> + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <stdlib.h> + +#define LOG_TAG "audit_rules" +#include <cutils/log.h> + +#include "libaudit.h" + +#define LINE_LEN 255 + +/* Reevaluate this number when support for more commands are added */ +#define MAX_OPTIONS 15 + +static int audit_rules_parse_and_add(int audit_fd, char *line) +{ + char *argv[MAX_OPTIONS]; + int argc; + int rc = 0, added_rule = 0; + char p; + int o; + size_t len; + struct audit_rule_data *rule; + + /* Strip crlf */ + line[strlen(line) -1] = '\0'; + + argv[0] = "auditd"; + + for (argc=1; argc < MAX_OPTIONS; argc++) { + argv[argc] = strsep(&line, " "); + if (argv[argc] == NULL) + break; + } + + optind = 0; + + while ((o = getopt(argc, argv, "w:e:p:")) != -1) { + switch(o) { + case 'w': + if (audit_add_dir(&rule, optarg)) { + SLOGE("Error adding rule"); + return -1; + } + added_rule = 1; + break; + case 'e': + if (audit_set_enabled(audit_fd, strtoul(optarg, NULL, 10))) + return -1; + break; + case 'p': + if (added_rule == 0) { + SLOGE("Specify rule type before permissions"); + return -1; + } + uint32_t perms = 0; + for (len=0; len < strlen(optarg); len++) { + switch(optarg[len]) { + case 'w': + perms |= AUDIT_PERM_WRITE; + break; + case 'e': + perms |= AUDIT_PERM_EXEC; + break; + case 'r': + perms |= AUDIT_PERM_READ; + break; + case 'a': + perms |= AUDIT_PERM_ATTR; + break; + default: + SLOGE("Unknown permission %c", optarg[len]); + break; + } + } + if (audit_update_watch_perms(rule, perms)) { + SLOGE("Could not set perms on rule"); + return -1; + } + break; + case '?': + SLOGE("Unsupported option: %c", optopt); + break; + } + } + + if (added_rule) { + rc = audit_send(audit_fd, AUDIT_ADD_RULE, rule, sizeof(*rule) + rule->buflen); + free(rule); + } + + return rc; +} + +int audit_rules_read_and_add(int audit_fd, const char *rulefile) +{ + int rc; + struct stat s; + char line[LINE_LEN]; + FILE *rules; + + rc = stat(rulefile, &s); + if (rc < 0) { + SLOGE("Could not read audit rules %s: %s", rulefile, strerror(errno)); + return 0; + } + + rules = fopen(rulefile, "r"); + if (rules == NULL) { + return -1; + } + + while (fgets(line, sizeof(line), rules)) { + SLOGE(line); + if (line[0] != '-') + continue; + if (audit_rules_parse_and_add(audit_fd, line) < 0) { + SLOGE("Could not read audit rules"); + return -1; + } + } + + fclose(rules); + return 0; +} diff --git a/auditd/audit_rules.h b/auditd/audit_rules.h new file mode 100644 index 0000000..16a617e --- /dev/null +++ b/auditd/audit_rules.h @@ -0,0 +1,24 @@ +/* + * Copyright 2013, Quark Security Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Written by Joshua Brindle <[email protected]> + */ + +#ifndef _AUDIT_RULES_H_ +#define _AUDIT_RULES_H_ + +extern int audit_rules_read_and_add(int audit_fd, const char *rulefile); + +#endif diff --git a/auditd/auditd.c b/auditd/auditd.c index 65ec855..875eed0 100644 --- a/auditd/auditd.c +++ b/auditd/auditd.c @@ -46,6 +46,7 @@ #include "libaudit.h" #include "audit_log.h" +#include "audit_rules.h" /* * TODO: @@ -61,6 +62,8 @@ #define AUDITD_LOG_FILE AUDITD_LOG_DIR "/audit.log" #define AUDITD_OLD_LOG_FILE AUDITD_LOG_DIR "/audit.old" +#define AUDITD_RULES_FILE "/data/misc/audit/audit.rules" + #define AUDITD_MAX_LOG_FILE_SIZE (1024 * AUDITD_MAX_LOG_FILE_SIZEKB) static volatile int quit = 0; @@ -189,6 +192,10 @@ int main(int argc, char *argv[]) goto err; } + if (audit_rules_read_and_add(audit_fd, AUDITD_RULES_FILE)) { + SLOGE("error reading audit rules: %s", strerror(errno)); + } + pfds.fd = audit_fd; pfds.events = POLLIN; diff --git a/auditd/libaudit.c b/auditd/libaudit.c index 06e5557..0f40be4 100644 --- a/auditd/libaudit.c +++ b/auditd/libaudit.c @@ -137,7 +137,7 @@ static int get_ack(int fd, int16_t seq) * @return * This function returns a positive sequence number on success, else -errno. */ -static int audit_send(int fd, int type, const void *data, unsigned int size) +int audit_send(int fd, int type, const void *data, unsigned int size) { int rc; static int16_t sequence = 0; @@ -220,6 +220,79 @@ out: return rc; } +int audit_update_watch_perms(struct audit_rule_data *rule, int perms) +{ + uint32_t i; + + if (rule == NULL) + return -1; + + for (i = 0; i < rule->field_count; i++) { + if (rule->fields[i] == AUDIT_PERM) { + rule->values[i] = perms; + break; + } + } + + if (rule->fields[i] == AUDIT_PERM) + return 0; + + if (rule->field_count > AUDIT_MAX_FIELDS) + return -2; + + rule->fields[rule->field_count] = AUDIT_PERM; + rule->fieldflags[rule->field_count] = AUDIT_EQUAL; + rule->values[rule->field_count] = perms; + rule->field_count++; + + return 0; +} + +int audit_add_dir(struct audit_rule_data **rulep, const char *path) +{ + int len = strlen(path); + struct audit_rule_data *rule; + *rulep = calloc(1, sizeof(*rule) + len); + rule = *rulep; + if (!rule) { + SLOGE("Out of memory"); + return -1; + } + + rule->flags = AUDIT_FILTER_EXIT; + rule->action = AUDIT_ALWAYS; + rule->field_count = 2; + + rule->mask[0] = ~0; + rule->fields[0] = AUDIT_DIR; + rule->fieldflags[0] = AUDIT_EQUAL; + rule->values[0] = len; + + rule->mask[1] = ~0; + rule->fields[1] = AUDIT_PERM; + rule->fieldflags[1] = AUDIT_EQUAL; + rule->values[1] = AUDIT_PERM_READ | AUDIT_PERM_WRITE | + AUDIT_PERM_EXEC | AUDIT_PERM_ATTR; + + rule->buflen = len; + memcpy(&rule->buf[0], path, len); + + return 0; +} + +int audit_set_enabled(int fd, uint32_t state) +{ + if (state > AUDIT_LOCKED) + return -1; + + struct audit_status s; + memset(&s, 0, sizeof(s)); + s.mask = AUDIT_STATUS_ENABLED; + s.enabled = state; + + return audit_send(fd, AUDIT_SET, &s, sizeof(s)); +} + int audit_set_pid(int fd, uint32_t pid, rep_wait_t wmode) { int rc; diff --git a/auditd/libaudit.h b/auditd/libaudit.h index fbaa7b9..bc21807 100644 --- a/auditd/libaudit.h +++ b/auditd/libaudit.h @@ -27,6 +27,10 @@ #define MAX_AUDIT_MESSAGE_LENGTH 8970 +#define AUDIT_OFF 0 +#define AUDIT_ON 1 +#define AUDIT_LOCKED 2 + typedef enum { GET_REPLY_BLOCKING=0, GET_REPLY_NONBLOCKING @@ -108,4 +112,52 @@ extern int audit_get_reply(int fd, struct audit_reply *rep, reply_t block, */ extern int audit_set_pid(int fd, uint32_t pid, rep_wait_t wmode); +/** + * sends a command to the audit netlink socket + * @param fd + * The fd returned by a call to audit_open() + * @param type + * message type, see audit.h in the kernel + * @param data + * opaque data pointer + * @param size + * size of data in *data + * @return + * This function returns 0 on success, -errno on error. + */ +extern int audit_send(int fd, int type, const void *data, unsigned int size); + +/** + * allocates a rule and adds a directory to watch, defaults to all permissions + * @param rulep + * pointer to pointer of an unallocated audit_rule_data, will be allocated, must be freed + * @param path + * path to add to the rule + * @return + * This function returns 0 on success, -errno on error. + */ +extern int audit_add_dir(struct audit_rule_data **rulep, const char *path); + +/** + * sets enabled flag, 0 for audit off, 1 for audit on, 2 for audit locked + * @param fd + * file descripter returned by audit_open() + * @param state + * 0 for audit off, 1 for audit on, 2 for audit locked + * @return + * This function returns 0 on success, -errno on error, -1 if already locked + */ +extern int audit_set_enabled(int fd, uint32_t state); + +/** + * Sets permissions for an already allocated watch rule + * @param rule + * rule to set permissions on + * @param perms + * permissions to set, AUDIT_PERM_{READ,WRITE,EXEC,ATTR} + * @return + * This function returns 0 on success, -1 if rule is NULL and -2 if there are too many fields + */ +extern int audit_update_watch_perms(struct audit_rule_data *rule, int perms); + #endif -- 1.7.9.5 -- This message was distributed to subscribers of the seandroid-list mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe seandroid-list" without quotes as the message.
