public inbox for linux-audit@redhat.com
 help / color / mirror / Atom feed
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 --]



  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