diff options
-rw-r--r-- | TODO | 17 | ||||
-rw-r--r-- | configure.ac | 9 | ||||
-rw-r--r-- | daemon/Makefile.am | 2 | ||||
-rw-r--r-- | daemon/acl.c | 175 | ||||
-rw-r--r-- | generator/actions.ml | 82 | ||||
-rw-r--r-- | po/POTFILES | 1 | ||||
-rw-r--r-- | src/MAX_PROC_NR | 2 |
7 files changed, 274 insertions, 14 deletions
@@ -588,20 +588,11 @@ is very poorly designed and essentially impossible for us to use: particularly if we also want to maintain backwards compatibility with Ruby 1.8, and/or maintain volatile VALUEs on the stack. -ACLs and capabilities ---------------------- - -We need to model both filesystem ACLs and filesystem capabilities -through the API. This is particularly important in order to be able -to implement SCAP. - -ACLs can be read and written using the acl(5) library and the -functions like acl_set_file(3) etc. +Filesystem capabilities +----------------------- -Setting the ACL on a file sets the extended attribute -'system.posix_acl_access' to a binary blob. The kernel has a whole -bunch of complex code that seems to interpret these -(linux/fs/posix_acl.c). +We need to model filesystem capabilities through the API. This is +particularly important in order to be able to implement SCAP. Filesystem capabilities can be read and written using the libcap(3) library and functions like cap_get_file, cap_set_file. diff --git a/configure.ac b/configure.ac index 1869430d..6f930f5b 100644 --- a/configure.ac +++ b/configure.ac @@ -692,6 +692,15 @@ AC_CHECK_LIB([magic],[magic_file], ], [AC_MSG_WARN([libmagic not found, some core features will be disabled])]) +dnl POSIX acl library (highly recommended) +AC_CHECK_LIB([acl],[acl_from_text], + [AC_CHECK_HEADER([sys/acl.h], + [AC_SUBST([ACL_LIBS], [-lacl]) + AC_DEFINE([HAVE_ACL], [1], [Define to 1 if the POSIX acl library is available.]) + ], []) + ], + [AC_MSG_WARN([POSIX acl library not found])]) + dnl libvirt (highly recommended) AC_ARG_WITH([libvirt], [AS_HELP_STRING([--without-libvirt], diff --git a/daemon/Makefile.am b/daemon/Makefile.am index a57e6f4f..2f70c8ee 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -88,6 +88,7 @@ endif guestfsd_SOURCES = \ 9p.c \ + acl.c \ actions.h \ available.c \ augeas.c \ @@ -181,6 +182,7 @@ guestfsd_SOURCES = \ guestfsd_LDADD = \ liberrnostring.a \ libprotocol.a \ + $(ACL_LIBS) \ $(SELINUX_LIB) \ $(AUGEAS_LIBS) \ $(HIVEX_LIBS) \ diff --git a/daemon/acl.c b/daemon/acl.c new file mode 100644 index 00000000..710d3857 --- /dev/null +++ b/daemon/acl.c @@ -0,0 +1,175 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2012 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <limits.h> +#include <unistd.h> + +#include "guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" +#include "optgroups.h" + +#if defined(HAVE_ACL) + +#include <sys/types.h> +#include <sys/acl.h> + +int +optgroup_acl_available (void) +{ + return 1; +} + +char * +do_acl_get_file (const char *path, const char *acltype) +{ + acl_type_t t; + acl_t acl; + char *r, *ret; + + if (STREQ (acltype, "access")) + t = ACL_TYPE_ACCESS; + else if (STREQ (acltype, "default")) + t = ACL_TYPE_DEFAULT; + else { + reply_with_error ("invalid acltype parameter: %s", acltype); + return NULL; + } + + CHROOT_IN; + acl = acl_get_file (path, t); + CHROOT_OUT; + + if (acl == NULL) { + reply_with_perror ("%s", path); + return NULL; + } + + r = acl_to_text (acl, NULL); + if (r == NULL) { + reply_with_perror ("acl_to_text"); + acl_free (acl); + return NULL; + } + + acl_free (acl); + + /* 'r' is not an ordinary pointer that can be freed with free(3)! + * In the current implementation of libacl, if you try to do that it + * will segfault. We have to duplicate this into an ordinary + * buffer, then call acl_free (r). + */ + ret = strdup (r); + if (ret == NULL) { + reply_with_perror ("strdup"); + acl_free (r); + return NULL; + } + acl_free (r); + + return ret; /* caller frees */ +} + +int +do_acl_set_file (const char *path, const char *acltype, const char *aclstr) +{ + acl_type_t t; + acl_t acl; + int r; + + if (STREQ (acltype, "access")) + t = ACL_TYPE_ACCESS; + else if (STREQ (acltype, "default")) + t = ACL_TYPE_DEFAULT; + else { + reply_with_error ("invalid acltype parameter: %s", acltype); + return -1; + } + + acl = acl_from_text (aclstr); + if (acl == NULL) { + reply_with_perror ("could not parse acl string: %s: acl_from_text", aclstr); + return -1; + } + + CHROOT_IN; + r = acl_set_file (path, t, acl); + CHROOT_OUT; + + if (r == -1) { + reply_with_perror ("%s", path); + acl_free (acl); + return -1; + } + + acl_free (acl); + + return 0; +} + +int +do_acl_delete_def_file (const char *dir) +{ + int r; + + CHROOT_IN; + r = acl_delete_def_file (dir); + CHROOT_OUT; + + if (r == -1) { + reply_with_perror ("%s", dir); + return -1; + } + + return 0; +} + +#else /* no acl library */ + +/* Note that the wrapper code (daemon/stubs.c) ensures that the + * functions below are never called because + * optgroup_acl_available returns false. + */ +int +optgroup_acl_available (void) +{ + return 0; +} + +char * +do_acl_get_file (const char *path, const char *acltype) +{ + abort (); +} + +int +do_acl_set_file (const char *path, const char *acltype, const char *acl) +{ + abort (); +} + +int +do_acl_delete_def_file (const char *dir) +{ + abort (); +} + +#endif /* no acl library */ diff --git a/generator/actions.ml b/generator/actions.ml index 020dd947..0a222273 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -10408,6 +10408,88 @@ Make the C<lost+found> directory, normally in the root directory of an ext2/3/4 filesystem. C<mountpoint> is the directory under which we try to create the C<lost+found> directory." }; + { defaults with + name = "acl_get_file"; + style = RString "acl", [Pathname "path"; String "acltype"], []; + proc_nr = Some 375; + optional = Some "acl"; + tests = []; (* tested by acl_set_file *) + shortdesc = "get the POSIX ACL attached to a file"; + longdesc = "\ +This function returns the POSIX Access Control List (ACL) attached +to C<path>. The ACL is returned in \"long text form\" (see L<acl(5)>). + +The C<acltype> parameter may be: + +=over 4 + +=item C<access> + +Return the ordinary (access) ACL for any file, directory or +other filesystem object. + +=item C<default> + +Return the default ACL. Normally this only makes sense if +C<path> is a directory. + +=back" }; + + { defaults with + name = "acl_set_file"; + style = RErr, [Pathname "path"; String "acltype"; String "acl"], []; + proc_nr = Some 376; + optional = Some "acl"; + tests = [ + InitScratchFS, Always, TestRun ( + [["touch"; "/acl_set_file_0"]; + ["acl_set_file"; "/acl_set_file_0"; "access"; "user::r-x,group::r-x,other::r-x"]; + ["acl_get_file"; "/acl_set_file_0"; "access"]]); + ]; + shortdesc = "set the POSIX ACL attached to a file"; + longdesc = "\ +This function sets the POSIX Access Control List (ACL) attached +to C<path>. The C<acl> parameter is the new ACL in either +\"long text form\" or \"short text form\" (see L<acl(5)>). + +The C<acltype> parameter may be: + +=over 4 + +=item C<access> + +Set the ordinary (access) ACL for any file, directory or +other filesystem object. + +=item C<default> + +Set the default ACL. Normally this only makes sense if +C<path> is a directory. + +=back" }; + + { defaults with + name = "acl_delete_def_file"; + style = RErr, [Pathname "dir"], []; + proc_nr = Some 377; + optional = Some "acl"; + tests = [ + (* Documentation for libacl says this should fail, but it doesn't. + * Therefore disable this test. + *) + InitScratchFS, Disabled, TestLastFail ( + [["touch"; "/acl_delete_def_file_0"]; + ["acl_delete_def_file"; "/acl_delete_def_file_0"]]); + InitScratchFS, Always, TestRun ( + [["mkdir"; "/acl_delete_def_file_1"]; + ["acl_set_file"; "/acl_delete_def_file_1"; "default"; "user::r-x,group::r-x,other::r-x"]; + ["acl_delete_def_file"; "/acl_delete_def_file_1"]]); + ]; + shortdesc = "delete the default POSIX ACL of a directory"; + longdesc = "\ +This function deletes the default POSIX Access Control List (ACL) +attached to directory C<dir>." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/po/POTFILES b/po/POTFILES index ece787a8..7e289eb9 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -4,6 +4,7 @@ cat/virt-cat.c cat/virt-filesystems.c cat/virt-ls.c daemon/9p.c +daemon/acl.c daemon/augeas.c daemon/available.c daemon/base64.c diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 38a45c3e..66a899ac 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -374 +377 |