All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.