patch for linux capabilities

jw schultz jw at pegasys.ws
Mon Jan 26 20:17:52 GMT 2004


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 at pegasys.ws

		Remember Cernan and Schmitt


More information about the rsync mailing list