From owner-freebsd-security@FreeBSD.ORG Fri Aug 29 14:10:00 2008 Return-Path: Delivered-To: freebsd-security@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 33EA6106566B; Fri, 29 Aug 2008 14:10:00 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from pin.if.uz.zgora.pl (pin.if.uz.zgora.pl [212.109.128.251]) by mx1.freebsd.org (Postfix) with ESMTP id 9BE498FC3A; Fri, 29 Aug 2008 14:09:59 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: by pin.if.uz.zgora.pl (Postfix, from userid 1001) id 4757E39CFA; Fri, 29 Aug 2008 15:59:05 +0200 (CEST) Date: Fri, 29 Aug 2008 15:59:05 +0200 From: Edward Tomasz Napierala To: trustedbsd-discuss@freebsd.org, freebsd-current@freebsd.org Message-ID: <20080829135905.GA25236@pin.if.uz.zgora.pl> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-2 Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) X-Mailman-Approved-At: Sun, 31 Aug 2008 13:33:13 +0000 Cc: Subject: NFSv4 ACLs. X-BeenThere: freebsd-security@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Security issues \[members-only posting\]" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 29 Aug 2008 14:10:00 -0000 Right now, FreeBSD supports one type of ACLs - so called POSIX.1e ACLs. They are natural extension of the traditional Unix permissions, and for a long time were the only nonproprietary ACL type in Unix systems. Times change, and now there are several problems with them: they never actually become standard (the draft they are based on was withdrawn); this results in minor incompatibilities related to e.g. umask handling; they don't fit into Windows or NFSv4 security model, which makes interoperability between these systems harder; finally, they don't work with ZFS. The aim of my GSoC project was to implement NFSv4 ACLs in a similar way POSIX.1e ACLs are supported. That was done by extending user utilities (setfacl(1)/getfacl(1)), libc API and adding neccessary kernel stuff. Semantics is supposed to be identical to the one in SunOS. There is also a wrapper (distributed separately) that implements SunOS-compatible acl(2)/facl(2) API, to make porting applications like Samba easier. Userland tools - setfacl(1) and getfacl(1) were modified to work with new ACLs. The former was slightly restructured to make it more readable. Most of the setfacl(1) options work the same way with NFS4 ACLs as they do with POSIX.1e ACLs. However, things like "-m" or "-x" don't always fit in a model where ordering of entries matters and there may be more than one identical entry. Thus, two more options were added - "-a", that adds ACL entry at the specified position, and '-x number', which removes ACL entry at a specified position. Manual pages were updated as appropriate. ACL format is the same as SunOS "positional", aka "compact", format. For example: [trasz@traszkan:~]$ getfacl / # file: / # owner: root # group: wheel owner@:--------------:------:deny owner@:rwxp---A-W-Co-:------:allow group@:-w-p----------:------:deny group@:r-x-----------:------:allow everyone@:-w-p---A-W-Co-:------:deny everyone@:r-x---a-R-c--s:------:allow There is also a "verbose" format, similar - but not identical - to the SunOS counterpart: [trasz@traszkan:~]$ getfacl -v / # file: / # owner: root # group: wheel owner@:::deny owner@:read_data/write_data/execute/append_data/write_attributes/write_xattr/write_acl/write_owner::allow group@:write_data/append_data::deny group@:read_data/execute::allow everyone@:write_data/append_data/write_attributes/write_xattr/write_acl/write_owner::deny everyone@:read_data/execute/read_attributes/read_xattr/read_acl/synchronize::allow The ls(1) and chmod(1) utilities were modified to remove POSIX.1e-specific assumptions. The following functions were added to the acl(3) API: acl_add_flag_np, acl_clear_flags_np, acl_create_entry_np, acl_delete_entry_np, acl_delete_flag_np, acl_get_extended_np, acl_get_flag_np, acl_get_flagset_np, acl_set_extended_np, acl_set_flagset_np, acl_to_text_np, acl_is_trivial_np, acl_strip_np, acl_get_brand_np. The flags part is source compatible with Darwin, other functions don't have their counterparts there. Manual pages were added or modified as neccessary. There should be no backward incompatible changes. As for the libc internals - "struct acl" et al were extended to make room for additional entries required by NFS4. Mechanism called "branding" was introduced to prevent API users from mixing POSIX and NFS4 specific stuff in a single ACL. One thing that still needs to be done is to add a few binary compatibility wrappers; these places are marked with 'XXX' in the code. ACL_MAX_ENTRIES was increased from 32 to 204. Syscall interface remains the same, except for a changed "type" constants, in order to preserve backwards compatibility with older libc. VOP_SETACL, VOP_GETACL and VOP_ACLCHECK interface remains the same, except for modified "struct acl". VOP_ACCESS changed a little - second argument was changed from "int" to "vaccess_t"; there should be no functional changes related to that. There are differences related to permissions granularity; as long as VOP_ACCESS implementation simply passes the "a_mode" parameter to the proper vaccess(9) routine, there should be no difference in behaviour. Adding granularity required adding some VWHATEVER defines to sys/vnode.h, adding several VOP_ACCESS checks in the syscall layer, replacing VADMIN with more specific permission in UFS and adding a unixify_vaccess() routine that "strips the granularity" from the mode. This routine is used in vaccess(9) and vaccess_acl_posix1e(9). Filesystem-independent functionality was implemented in kern/subr_acl_nfs4.c. This includes vaccess_acl_nfs4, routines to recompute ACL after the mode change, recompute the mode after ACL change, compute inherited ACL, and check the ACL for correctness. Implementation is based on draft-ietf-nfsv4-minorversion1-03, with small tweaks to make it behave exactly as ZFS does. Later drafts are unfortunately less specific, probably to make it possible to actually pass the voting. Note that these routines are used only by UFS; ZFS has its own implementation. Support for NFS4 ACL storage and retrieval was added to ufs/ufs/ufs_acl.c. Stored ACLs are variable in size, to reduce disk space used. Other parts of UFS (ufs_vnops.c and ufs_lookup.c) were modified to implement granularity. Support for NFS4 ACL storage and retrival was added to ZFS. It interfaces with ZFS own ACL mechanisms through wrappers. Two sets of unit tests were implemented. First, to test permission checks, was implemented as a part of fstest, tools/regression/fstest/tests/granular. Second, an "utility-level" test, is in tools/regression/acltools. It checks behaviour from the command-line point of view. It verifies the correct behaviour of getfacl(1), setfacl(1), cp(1) and mv(1) utilities (which obviously requires correct operation of the libc part), as well as recomputing ACLs on mode change, recomputing mode on ACL change, and ACL inheritance, which are performed by the kernel. These tests were used to make sure UFS behaves exactly the same way ZFS does. There is also a basic test for POSIX.1e ACLs as well, to make sure that part of functionality wasn't broken. The code is in working state. It can be found in Perforce: //depot/projects/soc2008/trasz_nfs4acl/... Patch against yesterdays -CURRENT is at: http://people.freebsd.org/~trasz/20080827-nfs4acls.diff I'd like to ask you for review, comments and suggestions. And testing, of course - this is just a prototype, but a working one. This work was done as a Google Summer of Code project. Thanks, Google :-)