From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric Paris Subject: Re: [PATCH 1/7] audit: implement generic feature setting and retrieving Date: Fri, 24 May 2013 12:28:40 -0400 Message-ID: <1369412920.2514.12.camel@dhcp137-228.rdu.redhat.com> References: <1369411910-13777-1-git-send-email-eparis@redhat.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-IksZ2G/Pf7fcCbwXDwXD" Return-path: Received: from [10.10.49.222] (vpn-49-222.rdu2.redhat.com [10.10.49.222]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r4OGSh80001594 for ; Fri, 24 May 2013 12:28:43 -0400 In-Reply-To: <1369411910-13777-1-git-send-email-eparis@redhat.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-audit-bounces@redhat.com Errors-To: linux-audit-bounces@redhat.com To: linux-audit@redhat.com List-Id: linux-audit@redhat.com --=-IksZ2G/Pf7fcCbwXDwXD Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit On Fri, 2013-05-24 at 12:11 -0400, Eric Paris wrote: > The audit_status structure was not designed with extensibility in mind. > Define a new AUDIT_SET_FEATURE message type which takes a new structure > of bits where things can be enabled/disabled/locked one at a time. This > structure should be able to grow in the future while maintaining forward > and backward compatibility (based loosly on the ideas from capabilities > and prctl) > > This does not actually add any features, but is just infrastructure to > allow new on/off types of audit system features. > > Signed-off-by: Eric Paris Attached you will find the test program I used to check that things were working correctly. It should give an idea to Steve how we can program the features support in userspace. I believe it fits very nicely to have a new syntax in audit.rules to set (and lock if needed/wanted) these features. netlink.c is just some helper code I stole from the audit tree to get some functions which weren't exposed externally. The only part really interesting is test.c. You will also need the include/uapi/linux/audit.h file from this patch to build test.c -Eric --=-IksZ2G/Pf7fcCbwXDwXD Content-Disposition: attachment; filename="Makefile" Content-Type: text/x-makefile; name="Makefile"; charset="UTF-8" Content-Transfer-Encoding: 7bit all: test test: test.c gcc -o test -Wall -W test.c netlink.c -laudit --=-IksZ2G/Pf7fcCbwXDwXD Content-Disposition: attachment; filename="netlink.c" Content-Type: text/x-csrc; name="netlink.c"; charset="UTF-8" Content-Transfer-Encoding: 7bit #include #include #include #include #include #include #include #include #include #include #include "private.h" int check_ack(int fd) { int rc, retries = 80; struct audit_reply rep; struct pollfd pfd[1]; retry: pfd[0].fd = fd; pfd[0].events = POLLIN; do { rc = poll(pfd, 1, 500); /* .5 second */ } while (rc < 0 && errno == EINTR); /* We don't look at rc from above as it doesn't matter. We are * going to try to read nonblocking just in case packet shows up. */ /* NOTE: whatever is returned is treated as the errno */ rc = audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, MSG_PEEK); if (rc == -EAGAIN && retries) { retries--; goto retry; } else if (rc < 0) return rc; else if (rc == 0) return -EINVAL; /* This can't happen anymore */ else if (rc > 0 && rep.type == NLMSG_ERROR) { int error = rep.error->error; /* Eat the message */ (void)audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0); /* NLMSG_ERROR can indicate success, only report nonzero */ if (error) { errno = -error; return error; } } return 0; } int audit_send(int fd, int type, const void *data, unsigned int size) { static int sequence = 0; struct audit_message req; int retval; struct sockaddr_nl addr; /* Due to user space library callbacks, there's a chance that a -1 for the fd could be passed. Just check for and handle it. */ if (fd < 0) { errno = EBADF; return -errno; } if (NLMSG_SPACE(size) > MAX_AUDIT_MESSAGE_LENGTH) { errno = EINVAL; return -errno; } if (++sequence < 0) sequence = 1; memset(&req, 0, sizeof(req)); req.nlh.nlmsg_len = NLMSG_SPACE(size); req.nlh.nlmsg_type = type; req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; req.nlh.nlmsg_seq = sequence; if (size && data) memcpy(NLMSG_DATA(&req.nlh), data, size); memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_pid = 0; addr.nl_groups = 0; do { retval = sendto(fd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr)); } while (retval < 0 && errno == EINTR); if (retval == (int)req.nlh.nlmsg_len) { if ((retval = check_ack(fd)) == 0) return sequence; else return retval; } if (retval < 0) return -errno; return 0; } int get_reply(int fd, void *data, size_t data_len) { int len; struct sockaddr_nl nladdr; socklen_t nladdrlen = sizeof(nladdr); if (fd < 0) return -EBADF; retry: len = recvfrom(fd, data, data_len, 0, (struct sockaddr*)&nladdr, &nladdrlen); if (len < 0) { if (errno == EINTR) goto retry; return -errno; } if (nladdrlen != sizeof(nladdr)) return -EPROTO; if (nladdr.nl_pid) return -EINVAL; return len; } --=-IksZ2G/Pf7fcCbwXDwXD Content-Disposition: attachment; filename="private.h" Content-Type: text/x-chdr; name="private.h"; charset="UTF-8" Content-Transfer-Encoding: 7bit int check_ack(int fd); int audit_send(int fd, int type, const void *data, unsigned int size); int get_reply(int fd, void *data, size_t data_len); --=-IksZ2G/Pf7fcCbwXDwXD Content-Disposition: attachment; filename="test.c" Content-Type: text/x-csrc; name="test.c"; charset="UTF-8" Content-Transfer-Encoding: 7bit #include #include #include #include #include #include #include #include #include #include #include #include "private.h" #define UNSET_FEATURE_MASK AUDIT_FEATURE_TO_MASK(AUDIT_FEATURE_ONLY_UNSET_LOGINUID) #define IMMUTABLE_FEATURE_MASK AUDIT_FEATURE_TO_MASK(AUDIT_FEATURE_LOGINUID_IMMUTABLE) static void print_af(char *prefix, struct audit_features *af) { fprintf(stdout, "%s vers=%d mask=%08x feature=%08x lock=%08x\n", prefix, af->vers, af->mask, af->features, af->lock); } static int get_and_print(int fd) { struct audit_features af, *paf; char buf[4096]; int rc; /* get the features */ rc = audit_send(fd, AUDIT_GET_FEATURE, &af, sizeof(af)); if (rc < 0) return rc; rc = get_reply(fd, buf, sizeof(buf)); if (rc < 0) return rc; paf = NLMSG_DATA(buf); print_af("FROM:", paf); return 0; } static int set_features(int fd, struct audit_features *af) { int rc; print_af("TO:", af); rc = audit_send(fd, AUDIT_SET_FEATURE, af, sizeof(*af)); if (rc < 0) { perror("audit_send"); return rc; } rc = get_and_print(fd); if (rc < 0) return rc; return 0; } int main(int argc, char *argv[]) { int fd; int rc; struct audit_features af; unsigned int mask = UNSET_FEATURE_MASK | IMMUTABLE_FEATURE_MASK; unsigned int features = 0; unsigned int lock = 0; if (argc < 4) { fprintf(stderr, "Dude, gets your args together, unset, immut, lock\n"); return -EINVAL; } if (atoi(argv[1])) features |= UNSET_FEATURE_MASK; if (atoi(argv[2])) features |= IMMUTABLE_FEATURE_MASK; if (atoi(argv[3])) lock = mask; fd = audit_open(); if (fd < 0) return fd; rc = get_and_print(fd); if (rc < 0) return rc; memset(&af, 0, sizeof(af)); /* set new features */ af.vers = AUDIT_FEATURE_VERSION; af.mask = mask; af.features = features; af.lock = lock; rc = set_features(fd, &af); if (rc < 0) return rc; return 0; } --=-IksZ2G/Pf7fcCbwXDwXD Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline --=-IksZ2G/Pf7fcCbwXDwXD--