RPM Community Forums

Mailing List Message of <rpm-devel>

Re: ACL and File Capability Support in RPM

From: Jeff Johnson <n3npq@mac.com>
Date: Tue 02 Sep 2008 - 21:32:09 CEST
Message-id: <0095047C-8422-4D7B-B0AA-2DB15FC13601@mac.com>

On Sep 2, 2008, at 2:53 PM, Serge E. Hallyn wrote:

> Quoting Andreas Gruenbacher (agruen@suse.de):
>> Hello all,
>>
>> I am trying to get the minimal bits and pieces into place for  
>> allowing us to
>> start using file capabilties.
>>
>> Currently, rpm neither supports acls nor file capabilities [1],  
>> and so when
>> they are needed, the usual way is to set them in the %post script.  
>> This
>> works, but unfortunately rpm then cannot --verify that a file has  
>> the right
>> permissions and capabilities attached.
>>
>> In am not aware of any cases where acls would actually be needed  
>> for packaged
>> files, so I think that we can safely leave acl support out of rpm  
>> for now. It
>> would be nice to check for acls in --verify, though.
>>
>> With file capabilities, things are different: distributions are  
>> going to start
>> using them instead of suid root binaries, and perhaps to run some  
>> daemons
>> with fewer privileges. The number of packages using capabilities  
>> won't be
>> huge, but sure more than a hand full.
>>
>> I believe that full capability support in rpm would be very  
>> useful. I am not
>> familiar enough with the rpm codebase, and I don't think I can  
>> implement full
>> file capability support efficiently.
>>
>> Nevertheless, rpm can meanwhile at least make sure in --verify  
>> that no files
>> have capabilities attached. To allow turning this check off, a new  
>> %verify
>> file list flag and a new --nocaps command line option seems to  
>> make sense for
>> me.
>>
>>
>> The attached two patches against (our version of) rpm-4.4.2 do the  
>> following:
>>
>>   verify-acls.diff
>>
>>     In --verify, also check for POSIX ACLs as part of the mode  
>> checks, and
>>     complain if any are found.
>>
>>   verify-file-capabilities.diff
>>
>>     Introduce a new "caps" %verify flag, and allocate a flag for it.
>>     Introduce a new --nocaps command line option.
>>     In --verify, also check for the presence of file capabilities,  
>> and
>>     complain if any are found. Use "P" as the indicator letter in the
>>     --verify output (in a new column).
>>
>>
>> What do you think -- do these patches look acceptable?
>
> It seems reasonable.  Of course people manually using file  
> capabilities
> will get annoying warnings, but given how serious stray file caps  
> would
> be it seems worthwhile.
>
> Hopefully someone will implement full capabilities support for rpm
> soon  :)  Alas, like yourself, I'm very unfamiliar with the code  
> (heck,
> with rpm itself).  If someone with more rpm familiarity wants to give
> it a shot, but would like some help, please don't hesitate to email  
> me.
>

The patches are a reasonable start at --verify, defining the  
necessary constants
and starting to wire up a verify framework.

However, the fundamental question that needs to be answered first is

     Do you want to attempt setting file capabilities and ACL's and  
XATTR's while
     installing *.rpm packages or not?

If you want to attempt setting values from *.rpm packages, there's some
some additional work needed to define tags to carry the data within  
*.rpm
packages, and to add to the install state machine.

OTOH, if you want to use --verify without adding additional metadata,  
then
a "reference point" which can be used to compare the installed  
capabilities
ACL's or XATTR's needs to be better defined.

(aside) This is basically the approach that SELinux file contexts  
(which are really XATTR's)
chose. Personally I think that was the wrong choice, but external  
store for file contexts was not hard to
implement.

In the real world there will be differences of opinion, so likely  
both approaches
need to be attempted to verify additional per-file attached metadata  
from either
*.rpm packages or from alternative external store.

Note that XAR already addresses the issues of ACL's and XATTR's (at  
least),
and otherwise permits extended per-file metadata transparently.

hth

73 de Jeff

> thanks,
> -serge
>
>> Thanks,
>> Andreas
>>
>> [1] http://ols.fedoraproject.org/OLS/Reprints-2008/hallyn-reprint.pdf
>>
>> -- 
>> Andreas Gruenbacher <agruen@suse.de>, SUSE Labs
>
>> Index: lib/verify.c
>> ===================================================================
>> --- lib/verify.c.orig
>> +++ lib/verify.c
>> @@ -5,6 +5,8 @@
>>
>>  #include "system.h"
>>
>> +#include <sys/xattr.h>
>> +
>>  #include <rpmcli.h>
>>
>>  #include "psm.h"
>> @@ -203,6 +205,16 @@ int rpmVerifyFile(const rpmts ts, const
>>  	    *res |= RPMVERIFY_MODE;
>>      }
>>
>> +    if (flags & RPMVERIFY_MODE) {
>> +	ssize_t size;
>> +
>> +	size = getxattr(fn, "system.posix_acl_access", NULL, 0);
>> +	if (size <= 0 && S_ISDIR(sb.st_mode))
>> +	    size = getxattr(fn, "system.posix_acl_default", NULL, 0);
>> +	if (size > 0)
>> +	    *res |= RPMVERIFY_MODE;
>> +    }
>> +
>>      if (flags & RPMVERIFY_RDEV) {
>>  	if (S_ISCHR(fmode) != S_ISCHR(sb.st_mode)
>>  	 || S_ISBLK(fmode) != S_ISBLK(sb.st_mode))
>
>> Index: lib/poptQV.c
>> ===================================================================
>> --- lib/poptQV.c.orig
>> +++ lib/poptQV.c
>> @@ -333,6 +333,9 @@ struct poptOption rpmVerifyPoptTable[] =
>>   { "nordev", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN,
>>  	&rpmQVKArgs.qva_flags, VERIFY_RDEV,
>>          N_("don't verify mode of files"), NULL },
>> + { "nocaps", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN,
>> +	&rpmQVKArgs.qva_flags, VERIFY_CAPS,
>> +        N_("don't verify capabilities of files"), NULL },
>>
>>   { "nocontexts", '\0', POPT_ARGFLAG_DOC_HIDDEN, NULL,  
>> RPMCLI_POPT_NOCONTEXTS,
>>  	N_("don't verify file security contexts"), NULL },
>> Index: lib/rpmcli.h
>> ===================================================================
>> --- lib/rpmcli.h.orig
>> +++ lib/rpmcli.h
>> @@ -130,7 +130,8 @@ typedef enum rpmVerifyAttrs_e {
>>      RPMVERIFY_MTIME	= (1 << 5),	/*!< from %verify(mtime) */
>>      RPMVERIFY_MODE	= (1 << 6),	/*!< from %verify(mode) */
>>      RPMVERIFY_RDEV	= (1 << 7),	/*!< from %verify(rdev) */
>> -	/* bits 8-14 unused, reserved for rpmVerifyAttrs */
>> +    RPMVERIFY_CAPS	= (1 << 8),	/*!< from %verify(caps) */
>> +	/* bits 9-14 unused, reserved for rpmVerifyAttrs */
>>      RPMVERIFY_CONTEXTS	= (1 << 15),	/*!< verify: from -- 
>> nocontexts */
>>  	/* bits 16-22 used in rpmVerifyFlags */
>>  	/* bits 23-27 used in rpmQueryFlags */
>> @@ -201,7 +202,8 @@ typedef enum rpmVerifyFlags_e {
>>      VERIFY_MTIME	= (1 << 5),	/*!< from --nomtime */
>>      VERIFY_MODE		= (1 << 6),	/*!< from --nomode */
>>      VERIFY_RDEV		= (1 << 7),	/*!< from --nodev */
>> -	/* bits 8-14 unused, reserved for rpmVerifyAttrs */
>> +    VERIFY_CAPS		= (1 << 8),	/*!< from --nocaps */
>> +	/* bits 9-14 unused, reserved for rpmVerifyAttrs */
>>      VERIFY_CONTEXTS	= (1 << 15),	/*!< verify: from --nocontexts */
>>      VERIFY_FILES	= (1 << 16),	/*!< verify: from --nofiles */
>>      VERIFY_DEPS		= (1 << 17),	/*!< verify: from --nodeps */
>> @@ -222,7 +224,7 @@ typedef enum rpmVerifyFlags_e {
>>
>>  #define	VERIFY_ATTRS	>    ( VERIFY_MD5 | VERIFY_SIZE |  
>> VERIFY_LINKTO | VERIFY_USER | VERIFY_GROUP | > -    VERIFY_MTIME |  
>> VERIFY_MODE | VERIFY_RDEV | VERIFY_CONTEXTS )
>> +    VERIFY_MTIME | VERIFY_MODE | VERIFY_RDEV | VERIFY_CAPS |  
>> VERIFY_CONTEXTS )
>>  #define	VERIFY_ALL	>    ( VERIFY_ATTRS | VERIFY_FILES |  
>> VERIFY_DEPS | VERIFY_SCRIPT | VERIFY_DIGEST |>       
>> VERIFY_SIGNATURE | VERIFY_HDRCHK )
>> Index: lib/verify.c
>> ===================================================================
>> --- lib/verify.c.orig
>> +++ lib/verify.c
>> @@ -228,6 +228,14 @@ int rpmVerifyFile(const rpmts ts, const
>>  	}
>>      }
>>
>> +    if (flags & RPMVERIFY_CAPS) {
>> +	    ssize_t size;
>> +
>> +	    size = getxattr(fn, "security.capability", NULL, 0);
>> +	    if (size > 0)
>> +		*res |= RPMVERIFY_CAPS;
>> +    }
>> +
>>      if (flags & RPMVERIFY_MTIME) {
>>  	if (sb.st_mtime != rpmfiFMtime(fi))
>>  	    *res |= RPMVERIFY_MTIME;
>> @@ -347,7 +355,7 @@ static int verifyHeader(QVA_t qva, const
>>  	    }
>>  	} else if (verifyResult || rpmIsVerbose()) {
>>  	    const char * size, * MD5, * link, * mtime, * mode;
>> -	    const char * group, * user, * rdev, *ctxt;
>> +	    const char * group, * user, * rdev, *caps, *ctxt;
>>  	    /*@observer@*/ static const char *const aok = ".";
>>  	    /*@observer@*/ static const char *const unknown = "?";
>>  	    /*@observer@*/ static const char *const ctxt_ignore = " ";
>> @@ -375,6 +383,7 @@ static int verifyHeader(QVA_t qva, const
>>  	    user = _verify(RPMVERIFY_USER, "U");
>>  	    group = _verify(RPMVERIFY_GROUP, "G");
>>  	    mode = _verify(RPMVERIFY_MODE, "M");
>> +	    caps = _verify(RPMVERIFY_CAPS, "P");
>>  	    ctxt = _verifyctxt(RPMVERIFY_CONTEXTS, "C");
>>
>>  #undef _verifyctxt
>> @@ -382,8 +391,9 @@ static int verifyHeader(QVA_t qva, const
>>  #undef _verifylink
>>  #undef _verify
>>
>> -	    sprintf(te, "%s%s%s%s%s%s%s%s%s %c %s",
>> -			size, mode, MD5, rdev, link, user, group, mtime, ctxt,
>> +	    sprintf(te, "%s%s%s%s%s%s%s%s%s%s %c %s",
>> +			size, mode, MD5, rdev, link, user, group, mtime, caps,
>> +			ctxt,
>>  			((fileAttrs & RPMFILE_CONFIG)	? 'c' :
>>  			 (fileAttrs & RPMFILE_DOC)	? 'd' :
>>  			 (fileAttrs & RPMFILE_GHOST)	? 'g' :
>> Index: doc/rpm.8
>> ===================================================================
>> --- doc/rpm.8.orig
>> +++ doc/rpm.8
>> @@ -93,6 +93,7 @@ rpm \- RPM Package Manager
>>   [\fB--nodigest\fR] [\fB--nosignature\fR]
>>   [\fB--nolinkto\fR] [\fB--nomd5\fR] [\fB--nosize\fR] [\fB--nouser 
>> \fR]
>>   [\fB--nogroup\fR] [\fB--nomtime\fR] [\fB--nomode\fR] [\fB--nordev 
>> \fR]
>> + [\fB--nocaps\fR]
>>
>>  .SS "install-options"
>>  .PP
>> @@ -708,6 +709,8 @@ Don't verify package or header signature
>>  \fB--nomode\fR
>>  .TP
>>  \fB--nordev\fR
>> +.TP
>> +\fB--nocaps\fR
>>  Don't verify the corresponding file attribute.
>>  .PP
>>  The format of the output is a string of 8 characters, a possible
>> @@ -742,6 +745,7 @@ the corresponding \fB--verify\fR test:
>>  \fBU\fR \fBU\fRser ownership differs
>>  \fBG\fR \fBG\fRroup ownership differs
>>  \fBT\fR m\fBT\fRime differs
>> +\fBP\fR ca\fBP\fRabilities differ
>>  .fi
>>
>>  .SS "DIGITAL SIGNATURE AND DIGEST VERIFICATION"
>> Index: build/files.c
>> ===================================================================
>> --- build/files.c.orig
>> +++ build/files.c
>> @@ -313,6 +313,7 @@ VFA_t verifyAttrs[] = {
>>      { "mtime",	0,	RPMVERIFY_MTIME },
>>      { "mode",	0,	RPMVERIFY_MODE },
>>      { "rdev",	0,	RPMVERIFY_RDEV },
>> +    { "caps",   0,      RPMVERIFY_CAPS },
>>      { NULL, 0,	0 }
>>  };
>>  /*@=exportlocal =exportheadervar@*/
>
> ______________________________________________________________________
> RPM Package Manager                                    http://rpm5.org
> Developer Communication List                        rpm-devel@rpm5.org
Received on Tue Sep 2 21:33:52 2008
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.