]> arthur.barton.de Git - netatalk.git/commitdiff
Writing metadata xattr on directories with sticky bit set, FR#94
authorRalph Boehme <rb@sernet.de>
Wed, 25 Jun 2014 09:46:03 +0000 (11:46 +0200)
committerRalph Boehme <rb@sernet.de>
Thu, 10 Jul 2014 16:03:07 +0000 (18:03 +0200)
Even though we may have write access to a directory, if the sticky bit
is set only the owner is allowed to write xattrs.

Add an option that enables behaviour to set the xattr as root, using
the fact that we can distinguish between a failing xattr set request
due to insufficient permissions (EACCES) or the sticky bit (EPERM):

  force xattr with sticky bit = yes|no (default: no)

Signed-off-by: Ralph Boehme <rb@sernet.de>
NEWS
doc/manpages/man5/afp.conf.5.xml
include/atalk/adouble.h
include/atalk/volume.h
libatalk/adouble/ad_flush.c
libatalk/util/netatalk_conf.c
man/man5/afp.conf.5.in

diff --git a/NEWS b/NEWS
index 9cf18b961275d12f6227730069be5cd20b1dd805..212272de7bf2f094099878d93b3946b9088397e2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@ Changes in 3.1.4
 ================
 * FIX: afpd: Hangs in Netatalk which causes it to stop responding to
        connections, bug #572.
+* NEW: afpd: new option "force xattr with sticky bit = yes|no"
+       (default: no), FR #94
 
 Changes in 3.1.3
 ================
index a8b4378c402dd02a644dbe03e3f5fced67a1b330..44e083c282f1f20a757ffaae0eb89ae60d290938 100644 (file)
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>force xattr with sticky bit =
+          <replaceable>BOOLEAN</replaceable> (default:
+          <emphasis>no</emphasis>) <type>(G/V)</type></term>
+
+          <listitem>
+            <para>Writing metadata xattr on directories with the
+            sticky bit set may fail even though we may have write
+            access to a directory, because if the sticky bit is set
+            only the owner is allowed to write xattrs.</para>
+
+            <para>By enabling this option Netatalk will write the
+            metadata xattr as root.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>guest account = <replaceable>name</replaceable>
           <type>(G)</type></term>
index f279d28cc67fb1a691c2320656e1cb2fbb14a1cd..40c92a11af01e046ceba97e59e15c3f1f0f1da9e 100644 (file)
@@ -249,6 +249,7 @@ struct adouble {
 #define ADVOL_UNIXPRIV   (1 << 2) /* adouble unix priv */
 #define ADVOL_INVDOTS    (1 << 3) /* dot files (.DS_Store) are invisible) */
 #define ADVOL_FOLLO_SYML (1 << 4)
+#define ADVOL_FORCE_STICKY_XATTR (1 << 5)
 
 /* lock flags */
 #define ADLOCK_CLR      (0)
index 084f5a0ad48cefd564492b8c4ccb90e7714824be..ad8be2b8421ff98a384a907b45145e3a6c0cc298 100644 (file)
@@ -118,6 +118,7 @@ typedef enum {lv_none = 0, lv_all = 1} lv_flags_t;
 #define AFPVOL_RO        (1 << 8)   /* read-only volume */
 #define AFPVOL_CHMOD_PRESERVE_ACL (1 << 9) /* try to preserve ACLs */
 #define AFPVOL_CHMOD_IGNORE (1 << 10) /* try to preserve ACLs */
+#define AFPVOL_FORCE_STICKY_XATTR (1 << 11) /* write metadata xattr as root on sticky dirs */
 #define AFPVOL_NOSTAT    (1 << 16)  /* advertise the volume even if we can't stat() it
                                      * maybe because it will be mounted later in preexec */
 #define AFPVOL_UNIX_PRIV (1 << 17)  /* support unix privileges */
index 6a1900c72f2f718e4e334139a19dd1b4bea43369..f049876dca0d498a4175e5c912e2d1aaf533c7d6 100644 (file)
@@ -286,8 +286,33 @@ static int ad_flush_hf(struct adouble *ad)
                 if (ad->ad_adflags & ADFLAGS_DIR) {
                     EC_NEG1_LOG( cwd = open(".", O_RDONLY) );
                     EC_NEG1_LOG( fchdir(ad_data_fileno(ad)) );
-                    EC_ZERO_LOGSTR( sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0),
-                                    "sys_lsetxattr(\"%s\"): %s", fullpathname(".") ,strerror(errno));
+
+                    ret = sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0);
+
+                    if (ret != 0) {
+                        if (errno != EPERM)
+                            EC_FAIL;
+
+                        if (!(ad->ad_options & ADVOL_FORCE_STICKY_XATTR))
+                            EC_FAIL;
+
+                        /*
+                         * This may be a directory with a sticky bit
+                         * set, which means even though we may have
+                         * write access to the directory, only the
+                         * owner is allowed to write xattrs
+                         */
+
+                        become_root();
+                        ret = sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0);
+                        unbecome_root();
+
+                        if (ret != 0) {
+                            LOG(log_error, logtype_ad, "ad_flush_hf: %s", strerror(errno));
+                            EC_FAIL;
+                        }
+                    }
+
                     EC_NEG1_LOG( fchdir(cwd) );
                     EC_NEG1_LOG( close(cwd) );
                     cwd = -1;
index 1a4f9fa64de8b6feec41932bb7a5c9dd39a0a5f6..a1d27311a4c2e9d786efdd35dfc431acef4af60e 100644 (file)
@@ -841,6 +841,8 @@ static struct vol *creatvol(AFPObj *obj,
         volume->v_preexec_close = 1;
     if (getoption_bool(obj->iniconfig, section, "root preexec close", preset, 0))
         volume->v_root_preexec_close = 1;
+    if (vdgoption_bool(obj->iniconfig, section, "force xattr with sticky bit", preset, 0))
+        volume->v_flags |= AFPVOL_FORCE_STICKY_XATTR;
 
     if ((val = getoption(obj->iniconfig, section, "ignored attributes", preset, obj->options.ignored_attr))) {
         if (strstr(val, "all")) {
@@ -895,6 +897,8 @@ static struct vol *creatvol(AFPObj *obj,
         volume->v_ad_options |= ADVOL_FOLLO_SYML;
     if ((volume->v_flags & AFPVOL_RO))
         volume->v_ad_options |= ADVOL_RO;
+    if ((volume->v_flags & AFPVOL_FORCE_STICKY_XATTR))
+        volume->v_ad_options |= ADVOL_FORCE_STICKY_XATTR;
 
     /* Mac to Unix conversion flags*/
     if ((volume->v_flags & AFPVOL_EILSEQ))
index 588911a56902312518fa72534e45ddc5fa145eba..5356bdf2e9434591015b67173aa131fa83603db1 100644 (file)
@@ -630,6 +630,13 @@ extmap file = \fIpath\fR \fB(G)\fR
 Sets the path to the file which defines file extension type/creator mappings\&. (default is @pkgconfdir@/extmap\&.conf)\&.
 .RE
 .PP
+force xattr with sticky bit = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G/V)\fR
+.RS 4
+Writing metadata xattr on directories with the sticky bit set may fail even though we may have write access to a directory, because if the sticky bit is set only the owner is allowed to write xattrs\&.
+.sp
+By enabling this option Netatalk will write the metadata xattr as root\&.
+.RE
+.PP
 guest account = \fIname\fR \fB(G)\fR
 .RS 4
 Specifies the user that guests should use (default is "nobody")\&. The name should be quoted\&.