From: Eric Paris <eparis@redhat.com>
To: linux-audit@redhat.com
Subject: Re: [PATCH 1/7] audit: implement generic feature setting and retrieving
Date: Fri, 24 May 2013 12:28:40 -0400 [thread overview]
Message-ID: <1369412920.2514.12.camel@dhcp137-228.rdu.redhat.com> (raw)
In-Reply-To: <1369411910-13777-1-git-send-email-eparis@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1174 bytes --]
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 <eparis@redhat.com>
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
[-- Attachment #2: Makefile --]
[-- Type: text/x-makefile, Size: 71 bytes --]
all: test
test: test.c
gcc -o test -Wall -W test.c netlink.c -laudit
[-- Attachment #3: netlink.c --]
[-- Type: text/x-csrc, Size: 2752 bytes --]
#include <libaudit.h>
#include <string.h>
#include <linux/audit.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/poll.h>
#include <stdio.h>
#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;
}
[-- Attachment #4: private.h --]
[-- Type: text/x-chdr, Size: 146 bytes --]
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);
[-- Attachment #5: test.c --]
[-- Type: text/x-csrc, Size: 1984 bytes --]
#include <libaudit.h>
#include <string.h>
#include <linux/audit.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/poll.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}
[-- Attachment #6: Type: text/plain, Size: 0 bytes --]
next prev parent reply other threads:[~2013-05-24 16:28 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-24 16:11 [PATCH 1/7] audit: implement generic feature setting and retrieving Eric Paris
2013-05-24 16:11 ` [PATCH 2/7] selinux: apply selinux checks on new audit message types Eric Paris
2013-05-24 16:11 ` [PATCH 3/7] audit: loginuid functions coding style Eric Paris
2013-05-24 16:11 ` [PATCH 4/7] audit: remove CONFIG_AUDIT_LOGINUID_IMMUTABLE Eric Paris
2013-05-24 16:11 ` [PATCH 5/7] audit: allow unsetting the loginuid (with priv) Eric Paris
2013-05-24 16:11 ` [PATCH 6/7] audit: audit feature to only allow unsetting the loginuid Eric Paris
2013-05-24 16:11 ` [PATCH 7/7] audit: audit feature to set loginuid immutable Eric Paris
2013-07-08 20:34 ` Steve Grubb
2013-07-08 20:51 ` Eric Paris
2013-07-08 21:26 ` Steve Grubb
2013-07-08 21:32 ` Eric Paris
2013-07-09 22:24 ` Steve Grubb
2013-07-09 23:51 ` LC Bruzenak
2013-07-10 13:46 ` Steve Grubb
2013-07-10 14:32 ` LC Bruzenak
2013-07-10 18:16 ` Eric Paris
2013-07-10 18:51 ` LC Bruzenak
2013-07-10 19:02 ` LC Bruzenak
2013-07-10 19:09 ` Eric Paris
2013-05-24 16:28 ` Eric Paris [this message]
2013-05-24 20:41 ` [PATCH 1/7] audit: implement generic feature setting and retrieving William Roberts
2013-05-24 20:56 ` William Roberts
2013-05-30 17:20 ` Richard Guy Briggs
2013-07-08 20:28 ` Steve Grubb
2013-07-08 21:55 ` Eric Paris
2013-07-09 1:18 ` William Roberts
2013-07-09 18:30 ` Steve Grubb
2013-07-09 20:59 ` Eric Paris
2013-07-09 22:08 ` Steve Grubb
2013-11-02 7:26 ` Richard Guy Briggs
2013-11-02 14:44 ` Eric Paris
2014-08-22 21:58 ` Steve Grubb
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1369412920.2514.12.camel@dhcp137-228.rdu.redhat.com \
--to=eparis@redhat.com \
--cc=linux-audit@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox