mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Neil Schemenauer <nas@arctrix.com>
To: linux-kernel@vger.kernel.org
Subject: capwrap: granting capabilities without fs support
Date: Thu, 8 Apr 2004 09:52:23 -0400	[thread overview]
Message-ID: <20040408135223.GA15870@mems-exchange.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 996 bytes --]

It seems people are once again wondering how to make use of
capabilities in Linux.  This module enables the use of Linux
capabilities on filesystems that do not support them.

To grant capabilities to an executable, a small wrapper file is
created that includes the path to an executable followed a
capability set written in hexadecimal.  When this file is executed
by the kernel, the executable is granted the specified capabilities.
The wrapper file must be owned by root and have the SUID bit set.

For example, to grant the CAP_NET_RAW (bit 13) capability to ping:

    # chmod -s /bin/ping
    # mv /bin/ping /bin/ping_real
    # echo '&/bin/ping_real 2000' > /bin/ping
    # chmod +xs /bin/ping

Another example is to grant the CAP_NET_BIND_SERVICE (bit 10) to
Apache:

    # echo '&/usr/sbin/apache 400' > httpd
    # chmod +xs httpd

The module is very small.  Perhaps it could be considered for
inclusion in the standard kernel.  I can work on a patch if people
are interested.

  Neil 

[-- Attachment #2: binfmt_capwrap.c --]
[-- Type: text/x-csrc, Size: 2634 bytes --]

/*
 *  linux/fs/binfmt_capwrap.c
 *
 *  Copyright (C) 2002  Neil Schemenauer
 */

#include <linux/module.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/binfmts.h>
#include <linux/init.h>
#include <linux/file.h>
#include <linux/smp_lock.h>
#include <linux/mount.h>
#include <linux/fs.h>


static int parse_cap(char **cp, unsigned int *cap)
{
	char *tok, *endp;
	int n;
	if ((tok = strsep(cp, " \t")) == NULL)
		return 0;
	n = simple_strtol(tok, &endp, 16);
	if (*endp != '\0')
		return 0;
	*cap = n;
	return 1;
}

static void grant_capabilities(struct linux_binprm *bprm, unsigned int caps)
{
	/* This may have to be more complicated if the kernel
	 * representation of capabilities changes.  Right now it's trivial.
	 */
	bprm->cap_effective |= caps;
	bprm->cap_permitted |= caps;
}

static int load_capwrap(struct linux_binprm *bprm, struct pt_regs *regs)
{
        struct inode * inode = bprm->file->f_dentry->d_inode;
	int mode = inode->i_mode;
	char exec_name[BINPRM_BUF_SIZE];
	char *cp, *tok;
	unsigned int caps = 0;
	struct file *file;
	int retval;

	/* must have magic */
	if ((bprm->buf[0] != '&'))
		return -ENOEXEC;

	/* must be owned by root */
	if (inode->i_uid != 0)
		return -ENOEXEC;

	/* must be SUID */
	if ((bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) ||
			!(mode & S_ISUID))
		return -ENOEXEC;

	/*
	 * Okay, parse the wrapper.
	 */

	allow_write_access(bprm->file);
	fput(bprm->file);
	bprm->file = NULL;

	/* terminate first line */
	bprm->buf[BINPRM_BUF_SIZE - 1] = '\0';
	if ((cp = strchr(bprm->buf, '\n')) == NULL)
		cp = bprm->buf+BINPRM_BUF_SIZE-1;
	*cp = '\0';

	/* name */
	cp = bprm->buf+1;
	if ((tok = strsep(&cp, " \t")) == NULL)
		return -ENOEXEC;
	strcpy(exec_name, tok);

	/* capabilities to add */
	if (!parse_cap(&cp, &caps))
		return -ENOEXEC;

	/*
	 * Restart the process with real executable's dentry.
	 */
	file = open_exec(exec_name);
	if (IS_ERR(file))
		return PTR_ERR(file);

	bprm->file = file;
	retval = prepare_binprm(bprm);
	if (retval < 0)
		return retval;

	grant_capabilities(bprm, caps);
	printk(KERN_DEBUG "capwrap: granted %s %x effective now %x\n",
			exec_name, caps, bprm->cap_effective);

	return search_binary_handler(bprm, regs);
}

struct linux_binfmt capwrap_format = {
	.module		= THIS_MODULE,
	.load_binary	= load_capwrap,
};

static int __init init_capwrap_binfmt(void)
{
	return register_binfmt(&capwrap_format);
}

static void __exit exit_capwrap_binfmt(void)
{
	unregister_binfmt(&capwrap_format);
}

module_init(init_capwrap_binfmt)
module_exit(exit_capwrap_binfmt)
MODULE_LICENSE("GPL");

             reply	other threads:[~2004-04-08 13:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-04-08 13:52 Neil Schemenauer [this message]
     [not found] <fa.g8lp2iv.1vlsqhp@ifi.uio.no>
2004-04-08 14:07 ` Andy Lutomirski
2004-04-08 16:56   ` Stephen Smalley
2004-04-08 17:12   ` Chris Wright

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=20040408135223.GA15870@mems-exchange.org \
    --to=nas@arctrix.com \
    --cc=linux-kernel@vger.kernel.org \
    /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

all inboxes | Powered by JetHome®