On Mon, Jan 26, 2004 at 01:36:23PM -0600, Michael Glasgow
wrote:> I was wondering if it might be possible for an rsync developer to
> look over the attached patch (tested on Linux 2.4.24 against the
> rsync-2.6.0 release), and offer suggestions on how I could improve it.
>
> Basically I want to use Linux finer grained capabilities to retain
> only CAP_SYS_CHROOT & CAP_DAC_READ_SEARCH when rsync drops root
> privs. That way I can take whole system backups as a (mostly)
> unprivileged user.
>
> Probably it should be some kind of config file option or something
> rather than a simple compile-time option. Also it would be nice
> to drop root much earlier if possible, but where?
>
> Any suggestions are much appreciated!
Start by putting the capability drop code into a seperate
function so that it doesn't complicate the existing code.
Then add a config file option to enable it on a
per-module basis (like use chroot and uid).
Also, i'd drop the capabilities after chroot() and not keep
the cap_sys_chroot.
You might want to evaluate different capability sets
depending on "read only" or other options and drop
capabilities after doing the chroot.
On a wider note, i'd rather this stay a patch for awhile and
become less Linux specific.
Content-Description: rsync.patch> diff -urN rsync-2.6.0.orig/clientserver.c rsync-2.6.0/clientserver.c
> --- rsync-2.6.0.orig/clientserver.c 2003-09-10 23:00:19.000000000 -0500
> +++ rsync-2.6.0/clientserver.c 2004-01-26 11:27:53.000000000 -0600
> @@ -25,6 +25,18 @@
> * rsyncd.
> **/
>
> +#ifdef HAVE_LINUX_CAPS
> +#ifdef _POSIX_SOURCE
> +#undef _POSIX_SOURCE
> +#include <sys/prctl.h>
> +#include <sys/capability.h>
> +#define _POSIX_SOURCE
> +#else
> +#include <sys/prctl.h>
> +#include <sys/capability.h>
> +#endif
> +#endif
> +
> #include "rsync.h"
>
> extern int module_id;
> @@ -217,6 +229,10 @@
> int start_glob=0;
> int ret;
> char *request=NULL;
> +#ifdef HAVE_LINUX_CAPS
> + cap_t cp;
> + cap_value_t newcaps[2] = { CAP_SYS_CHROOT, CAP_DAC_READ_SEARCH };
> +#endif
> extern int am_sender;
> extern int am_server;
> extern int am_daemon;
> @@ -373,12 +389,46 @@
> }
> #endif
>
> +#ifdef HAVE_LINUX_CAPS
> + if (setreuid(uid, 0)) {
> + rsyserr(FERROR, errno, "setreuid(%d,0) failed", (int) uid);
> + io_printf(f_out, "@ERROR: setreuid failed\n");
> + return -1;
> + }
> + if( prctl(PR_SET_KEEPCAPS, 1) < 0 ) {
> + rsyserr(FERROR, errno, "prctl failed");
> + io_printf(f_out, "@ERROR: prctl failed\n");
> + return -1;
> + }
> + if( (cp = cap_init()) == NULL ) {
> + rsyserr(FERROR, errno, "cap_init failed");
> + io_printf(f_out, "@ERROR: cap_init failed\n");
> + return -1;
> + }
> + if( cap_set_flag(cp, CAP_PERMITTED, 2, newcaps, CAP_SET) < 0 ||
> + cap_set_flag(cp, CAP_INHERITABLE, 2, newcaps, CAP_SET) < 0 ) {
> + rsyserr(FERROR, errno, "cap_set_flag failed");
> + io_printf(f_out, "@ERROR: cap_set_flag failed\n");
> + return -1;
> + }
> + if( cap_set_proc(cp) < 0 ) {
> + rsyserr(FERROR, errno, "cap_set_proc failed");
> + io_printf(f_out, "@ERROR: cap_set_proc failed\n");
> + return -1;
> + }
> +#endif
> +
> if (setuid(uid)) {
> rsyserr(FERROR, errno, "setuid %d failed", (int) uid);
> io_printf(f_out, "@ERROR: setuid failed\n");
> return -1;
> }
>
> +#ifdef HAVE_LINUX_CAPS
> + cap_set_flag(cp, CAP_EFFECTIVE, 2, newcaps, CAP_SET);
> + cap_set_proc(cp);
> +#endif
> +
> am_root = (getuid() == 0);
> }
>
> --
> To unsubscribe or change options:
http://lists.samba.org/mailman/listinfo/rsync
> Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html
--
________________________________________________________________
J.W. Schultz Pegasystems Technologies
email address: jw@pegasys.ws
Remember Cernan and Schmitt