Example #1
0
/* Obtain an audit buffer.  This routine does locking to obtain the
 * audit buffer, but then no locking is required for calls to
 * audit_log_*format.  If the tsk is a task that is currently in a
 * syscall, then the syscall is marked as auditable and an audit record
 * will be written at syscall exit.  If there is no associated task, tsk
 * should be NULL. */
struct audit_buffer *audit_log_start(struct audit_context *ctx)
{
	struct audit_buffer	*ab	= NULL;
	unsigned long		flags;
	struct timespec		t;
	int			serial	= 0;

	if (!audit_initialized)
		return NULL;

	if (audit_backlog_limit
	    && atomic_read(&audit_backlog) > audit_backlog_limit) {
		if (audit_rate_check())
			printk(KERN_WARNING
			       "audit: audit_backlog=%d > "
			       "audit_backlog_limit=%d\n",
			       atomic_read(&audit_backlog),
			       audit_backlog_limit);
		audit_log_lost("backlog limit exceeded");
		return NULL;
	}

	spin_lock_irqsave(&audit_freelist_lock, flags);
	if (!list_empty(&audit_freelist)) {
		ab = list_entry(audit_freelist.next,
				struct audit_buffer, list);
		list_del(&ab->list);
		--audit_freelist_count;
	}
Example #2
0
/* Move data from tmp buffer into an skb.  This is an extra copy, and
 * that is unfortunate.  However, the copy will only occur when a record
 * is being written to user space, which is already a high-overhead
 * operation.  (Elimination of the copy is possible, for example, by
 * writing directly into a pre-allocated skb, at the cost of wasting
 * memory. */
static void audit_log_move(struct audit_buffer *ab)
{
	struct sk_buff	*skb;
	char		*start;
	int		extra = ab->nlh ? 0 : NLMSG_SPACE(0);

	/* possible resubmission */
	if (ab->len == 0)
		return;

	skb = skb_peek(&ab->sklist);
	if (!skb || skb_tailroom(skb) <= ab->len + extra) {
		skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC);
		if (!skb) {
			ab->len = 0; /* Lose information in ab->tmp */
			audit_log_lost("out of memory in audit_log_move");
			return;
		}
		__skb_queue_tail(&ab->sklist, skb);
		if (!ab->nlh)
			ab->nlh = (struct nlmsghdr *)skb_put(skb,
							     NLMSG_SPACE(0));
	}
	start = skb_put(skb, ab->len);
	memcpy(start, ab->tmp, ab->len);
	ab->len = 0;
}
Example #3
0
/* Iterate over the skbuff in the audit_buffer, sending their contents
 * to user space. */
static inline int audit_log_drain(struct audit_buffer *ab)
{
	struct sk_buff *skb;

	while ((skb = skb_dequeue(&ab->sklist))) {
		int retval = 0;

		if (audit_pid) {
			if (ab->nlh) {
				ab->nlh->nlmsg_len   = ab->total;
				ab->nlh->nlmsg_type  = ab->type;
				ab->nlh->nlmsg_flags = 0;
				ab->nlh->nlmsg_seq   = 0;
				ab->nlh->nlmsg_pid   = ab->pid;
			}
			skb_get(skb); /* because netlink_* frees */
			retval = netlink_unicast(audit_sock, skb, audit_pid,
						 MSG_DONTWAIT);
		}
		if (retval == -EAGAIN && ab->count < 5) {
			++ab->count;
			skb_queue_tail(&ab->sklist, skb);
			audit_log_end_irq(ab);
			return 1;
		}
		if (retval < 0) {
			if (retval == -ECONNREFUSED) {
				printk(KERN_ERR
				       "audit: *NO* daemon at audit_pid=%d\n",
				       audit_pid);
				audit_pid = 0;
			} else
				audit_log_lost("netlink socket too busy");
		}
		if (!audit_pid) { /* No daemon */
			int offset = ab->nlh ? NLMSG_SPACE(0) : 0;
			int len    = skb->len - offset;
			printk(KERN_ERR "%*.*s\n",
			       len, len, skb->data + offset);
		}
		kfree_skb(skb);
		ab->nlh = NULL;
	}
	return 0;
}
/**
 *	tty_audit_buf_get	-	Get an audit buffer.
 *
 *	Get an audit buffer for @tty, allocate it if necessary.  Return %NULL
 *	if TTY auditing is disabled or out of memory.  Otherwise, return a new
 *	reference to the buffer.
 */
static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
		unsigned icanon)
{
	struct tty_audit_buf *buf, *buf2;
	unsigned long flags;

	buf = NULL;
	buf2 = NULL;
	spin_lock_irqsave(&current->sighand->siglock, flags);
	if (likely(!current->signal->audit_tty))
		goto out;
	buf = current->signal->tty_audit_buf;
	if (buf) {
		atomic_inc(&buf->count);
		goto out;
	}
	spin_unlock_irqrestore(&current->sighand->siglock, flags);

	buf2 = tty_audit_buf_alloc(tty->driver->major,
				   tty->driver->minor_start + tty->index,
				   icanon);
	if (buf2 == NULL) {
		audit_log_lost("out of memory in TTY auditing");
		return NULL;
	}

	spin_lock_irqsave(&current->sighand->siglock, flags);
	if (!current->signal->audit_tty)
		goto out;
	buf = current->signal->tty_audit_buf;
	if (!buf) {
		current->signal->tty_audit_buf = buf2;
		buf = buf2;
		buf2 = NULL;
	}
	atomic_inc(&buf->count);
	/* Fall through */
 out:
	spin_unlock_irqrestore(&current->sighand->siglock, flags);
	if (buf2)
		tty_audit_buf_free(buf2);
	return buf;
}