From 857f1ff91c8d862ccbc7d9692c45ef8b4e2ba446 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Thu, 3 Nov 2011 13:51:13 +0100 Subject: [PATCH] Fix for filesystem without NFSv4 ACL support on Solaris, Bug ID #3428389 --- NEWS | 1 + etc/afpd/acls.c | 5 ++--- etc/afpd/acls.h | 2 +- etc/afpd/afs.c | 5 +++-- etc/afpd/directory.c | 8 ++++---- etc/afpd/file.c | 6 +++--- etc/afpd/unix.c | 4 ++-- etc/afpd/unix.h | 2 +- etc/afpd/volume.c | 2 +- libatalk/acl/unix.c | 15 ++++++++------- 10 files changed, 26 insertions(+), 24 deletions(-) diff --git a/NEWS b/NEWS index 326f35b9..6e8aaa2a 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,7 @@ Changes in 2.2.2 * FIX: afpd: Fix an error when duplicating files that lacked an AppleDouble file which lead to a possible Finder crash * FIX: afpd: Read-only filesystems lead to afpd processes running as root +* FIX: afpd: Fix for filesystem without NFSv4 ACL support on Solaris * FIX: dbd: Better checking for duplicated or bogus CNIDs from AppleDouble files * FIX: Fix compilation error when AppleTalk support is disabled diff --git a/etc/afpd/acls.c b/etc/afpd/acls.c index d46f3605..1f4be067 100644 --- a/etc/afpd/acls.c +++ b/etc/afpd/acls.c @@ -1715,14 +1715,13 @@ int afp_setacl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size * This is the magic function that makes ACLs usable by calculating * the access granted by ACEs to the logged in user. */ -int acltoownermode(char *path, struct stat *st, struct maccess *ma) +int acltoownermode(const struct vol *vol, char *path, struct stat *st, struct maccess *ma) { EC_INIT; uint32_t rights = 0; if ( ! (AFPobj->options.flags & OPTION_ACL2MACCESS) - || (current_vol == NULL) - || ! (current_vol->v_flags & AFPVOL_ACLS)) + || ! (vol->v_flags & AFPVOL_ACLS)) return 0; LOG(log_maxdebug, logtype_afpd, "acltoownermode(\"%s/%s\", 0x%02x)", diff --git a/etc/afpd/acls.h b/etc/afpd/acls.h index c89fe9c8..273a9f13 100644 --- a/etc/afpd/acls.h +++ b/etc/afpd/acls.h @@ -113,6 +113,6 @@ int afp_setacl (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rb extern int acl_ldap_readconfig(char *name); /* Misc funcs */ -extern int acltoownermode(char *path, struct stat *st, struct maccess *ma); +extern int acltoownermode(const struct vol *vol, char *path, struct stat *st, struct maccess *ma); extern int check_vol_acl_support(const struct vol *vol); #endif diff --git a/etc/afpd/afs.c b/etc/afpd/afs.c index d045cd4e..377d5fb5 100644 --- a/etc/afpd/afs.c +++ b/etc/afpd/afs.c @@ -129,7 +129,8 @@ int afp_getdiracl(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *r #undef accessmode #endif -void afsmode( path, ma, dir, st ) +void afsmode( vol, path, ma, dir, st ) +const struct volume *vol; char *path; struct maccess *ma; struct dir *dir; @@ -153,7 +154,7 @@ struct stat *st; return; } - accessmode( path, ma, dir, st ); + accessmode(vol, path, ma, dir, st ); return; } diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index be52d36d..da7eb6c4 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -1410,7 +1410,7 @@ int check_access(char *path, int mode) if (!p) return -1; - accessmode(p, &ma, curdir, NULL); + accessmode(current_vol, p, &ma, curdir, NULL); if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE)) return -1; if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD)) @@ -1424,7 +1424,7 @@ int file_access(struct path *path, int mode) { struct maccess ma; - accessmode(path->u_name, &ma, curdir, &path->st); + accessmode(current_vol, path->u_name, &ma, curdir, &path->st); LOG(log_debug, logtype_afpd, "file_access(\"%s\"): mapped user mode: 0x%02x", path->u_name, ma.ma_user); @@ -1629,7 +1629,7 @@ int getdirparams(const struct vol *vol, break; case DIRPBIT_ACCESS : - accessmode( upath, &ma, dir , st); + accessmode(vol, upath, &ma, dir , st); *data++ = ma.ma_user; *data++ = ma.ma_world; @@ -1665,7 +1665,7 @@ int getdirparams(const struct vol *vol, case DIRPBIT_UNIXPR : /* accessmode may change st_mode with ACLs */ - accessmode( upath, &ma, dir, st); + accessmode(vol, upath, &ma, dir, st); aint = htonl(st->st_uid); memcpy( data, &aint, sizeof( aint )); diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 8402ebf1..36798904 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -394,9 +394,9 @@ int getmetadata(struct vol *vol, /* FIXME do we want a visual clue if the file is read only */ struct maccess ma; - accessmode( ".", &ma, dir , NULL); + accessmode(vol, ".", &ma, dir , NULL); if ((ma.ma_user & AR_UWRITE)) { - accessmode( upath, &ma, dir , st); + accessmode(vol, upath, &ma, dir , st); if (!(ma.ma_user & AR_UWRITE)) { ashort |= htons(ATTRBIT_NOWRITE); } @@ -563,7 +563,7 @@ int getmetadata(struct vol *vol, break; case FILPBIT_UNIXPR : /* accessmode may change st_mode with ACLs */ - accessmode( upath, &ma, dir , st); + accessmode(vol, upath, &ma, dir , st); aint = htonl(st->st_uid); memcpy( data, &aint, sizeof( aint )); diff --git a/etc/afpd/unix.c b/etc/afpd/unix.c index 0e444bcf..53a59b35 100644 --- a/etc/afpd/unix.c +++ b/etc/afpd/unix.c @@ -169,7 +169,7 @@ mode_t mode; * * dir parameter is used by AFS */ -void accessmode(char *path, struct maccess *ma, struct dir *dir _U_, struct stat *st) +void accessmode(const struct vol *vol, char *path, struct maccess *ma, struct dir *dir _U_, struct stat *st) { struct stat sb; @@ -181,7 +181,7 @@ void accessmode(char *path, struct maccess *ma, struct dir *dir _U_, struct stat } utommode( st, ma ); #ifdef HAVE_ACLS - acltoownermode(path, st, ma); + acltoownermode(vol, path, st, ma); #endif } diff --git a/etc/afpd/unix.h b/etc/afpd/unix.h index be7b7bfb..54ebf3d6 100644 --- a/etc/afpd/unix.h +++ b/etc/afpd/unix.h @@ -227,7 +227,7 @@ extern int setdeskowner (const uid_t, const gid_t); extern int setdirowner (const struct vol *, const char *, const uid_t, const gid_t); extern int setfilunixmode (const struct vol *, struct path*, const mode_t); extern int setfilowner (const struct vol *, const uid_t, const gid_t, struct path*); -extern void accessmode (char *, struct maccess *, struct dir *, struct stat *); +extern void accessmode (const struct vol *, char *, struct maccess *, struct dir *, struct stat *); #ifdef AFS #define accessmode afsmode diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index dd580cb8..9b9672ab 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -1939,7 +1939,7 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf if (!S_ISDIR(st.st_mode)) { continue; /* not a dir */ } - accessmode(volume->v_path, &ma, NULL, &st); + accessmode(volume, volume->v_path, &ma, NULL, &st); if ((ma.ma_user & (AR_UREAD | AR_USEARCH)) != (AR_UREAD | AR_USEARCH)) { continue; /* no r-x access */ } diff --git a/libatalk/acl/unix.c b/libatalk/acl/unix.c index 31027abe..9bad9c94 100644 --- a/libatalk/acl/unix.c +++ b/libatalk/acl/unix.c @@ -56,17 +56,17 @@ int get_nfsv4_acl(const char *name, ace_t **retAces) return 0; if ( ! (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) { - LOG(log_warning, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): special", getcwdpath(), name); + LOG(log_debug, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): special", getcwdpath(), name); return 0; } if ((ace_count = acl(name, ACE_GETACLCNT, 0, NULL)) == 0) { - LOG(log_warning, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): 0 ACEs", getcwdpath(), name); + LOG(log_debug, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): 0 ACEs", getcwdpath(), name); return 0; } if (ace_count == -1) { - LOG(log_error, logtype_afpd, "get_nfsv4_acl: acl('%s/%s', ACE_GETACLCNT): ace_count %i, error: %s", + LOG(log_debug, logtype_afpd, "get_nfsv4_acl: acl('%s/%s', ACE_GETACLCNT): ace_count %i, error: %s", getcwdpath(), name, ace_count, strerror(errno)); return -1; } @@ -205,10 +205,10 @@ int strip_nontrivial_aces(ace_t **saces, int sacecount) * Change mode of file preserving existing explicit ACEs * * nfsv4_chmod - * (1) reads objects ACL (acl1) + * (1) reads objects ACL (acl1), may return 0 or -1 NFSv4 ACEs on eg UFS fs * (2) removes all trivial ACEs from the ACL by calling strip_trivial_aces(), possibly * leaving 0 ACEs in the ACL if there were only trivial ACEs as mapped from the mode - * (3) calls chmod() with mode + * (3) calls chmod() with mode, we're done if step (1) returned 0 for noaces * (4) reads the changed ACL (acl2) which * a) might still contain explicit ACEs (up to onnv132) * b) will have any explicit ACE removed (starting with onnv145/Openindiana) @@ -225,8 +225,9 @@ int nfsv4_chmod(char *name, mode_t mode) LOG(log_debug, logtype_afpd, "nfsv4_chmod(\"%s/%s\", %04o)", getcwdpath(), name, mode); - if ((noaces = get_nfsv4_acl(name, &oacl)) == -1) /* (1) */ - goto exit; + if ((noaces = get_nfsv4_acl(name, &oacl)) < 1) /* (1) */ + return chmod(name, mode); + if ((noaces = strip_trivial_aces(&oacl, noaces)) == -1) /* (2) */ goto exit; -- 2.39.2