From 6667d65c86217fc3312bd6e3b19b548e4869b949 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Tue, 6 Mar 2012 15:16:01 +0100 Subject: [PATCH] Ignore EAs on symlinks --- libatalk/adouble/ad_open.c | 2 +- libatalk/vfs/ea_sys.c | 25 +++++++++------------ libatalk/vfs/extattr.c | 45 ++++++++++++++++++++++++++++---------- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c index 94549cd8..d4e84fd2 100644 --- a/libatalk/adouble/ad_open.c +++ b/libatalk/adouble/ad_open.c @@ -1333,7 +1333,7 @@ static int ad_open_rf_ea(const char *path, int adflags, int mode, struct adouble goto EC_CLEANUP; } #ifdef HAVE_EAFD - if (ad_meta_fileno(ad) == -1) + if (ad_meta_fileno(ad) < 0) EC_FAIL; if ((ad_reso_fileno(ad) = sys_getxattrfd(ad_meta_fileno(ad), AD_EA_RESO, oflags)) == -1) { if (!(adflags & ADFLAGS_CREATE)) { diff --git a/libatalk/vfs/ea_sys.c b/libatalk/vfs/ea_sys.c index fc6a4044..549aa6d1 100644 --- a/libatalk/vfs/ea_sys.c +++ b/libatalk/vfs/ea_sys.c @@ -81,8 +81,8 @@ int sys_get_easize(VFS_FUNC_ARGS_EA_GETSIZE) switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "sys_getextattr_size(%s): encountered symlink with kXAttrNoFollow", uname); - return AFP_OK; + LOG(log_debug, logtype_afpd, "sys_getextattr_size(%s): symlink with kXAttrNoFollow", uname); + return AFPERR_MISC; case ENOATTR: case ENOENT: @@ -157,8 +157,8 @@ int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT) switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): encountered symlink with kXAttrNoFollow", uname); - return AFP_OK; + LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): symlink with kXAttrNoFollow", uname); + return AFPERR_MISC; case ENOATTR: return AFPERR_MISC; @@ -220,18 +220,13 @@ int sys_list_eas(VFS_FUNC_ARGS_EA_LIST) if (ret == -1) switch(errno) { case OPEN_NOFOLLOW_ERRNO: - /* its a symlink and client requested O_NOFOLLOW */ - ret = AFPERR_BADTYPE; - goto exit; -#ifdef HAVE_ATTROPEN /* Solaris */ - case ENOATTR: - case ENOENT: + /* its a symlink and client requested O_NOFOLLOW, we pretend 0 EAs */ + LOG(log_debug, logtype_afpd, "sys_list_extattr(%s): symlink with kXAttrNoFollow", uname); ret = AFP_OK; goto exit; -#endif default: LOG(log_debug, logtype_afpd, "sys_list_extattr(%s): error opening atttribute dir: %s", uname, strerror(errno)); - ret= AFPERR_MISC; + ret = AFPERR_MISC; goto exit; } @@ -311,8 +306,8 @@ int sys_set_ea(VFS_FUNC_ARGS_EA_SET) switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): encountered symlink with kXAttrNoFollow", - getcwdpath(), uname, attruname); + LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s\", ea:'%s'): symlink with kXAttrNoFollow", + uname, attruname); return AFP_OK; case EEXIST: LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): EA already exists", @@ -365,7 +360,7 @@ int sys_remove_ea(VFS_FUNC_ARGS_EA_REMOVE) switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "sys_remove_ea(%s/%s): encountered symlink with kXAttrNoFollow", uname); + LOG(log_debug, logtype_afpd, "sys_remove_ea(%s/%s): symlink with kXAttrNoFollow", uname); return AFP_OK; case EACCES: LOG(log_debug, logtype_afpd, "sys_remove_ea(%s/%s): error: %s", uname, attruname, strerror(errno)); diff --git a/libatalk/vfs/extattr.c b/libatalk/vfs/extattr.c index db325328..51301461 100644 --- a/libatalk/vfs/extattr.c +++ b/libatalk/vfs/extattr.c @@ -60,6 +60,7 @@ #include #include #include +#include /******** Solaris EA helper function prototypes ********/ #ifdef HAVE_ATTROPEN @@ -263,7 +264,7 @@ ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t return retval ? retval : valuelength; #elif defined(HAVE_ATTROPEN) ssize_t ret = -1; - int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); + int attrfd = solaris_attropen(path, name, O_RDONLY | O_NOFOLLOW, 0); if (attrfd >= 0) { ret = solaris_read_xattr(attrfd, value, size); close(attrfd); @@ -513,7 +514,7 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size) return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW); #elif defined(HAVE_ATTROPEN) ssize_t ret = -1; - int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); + int attrdirfd = solaris_attropen(path, ".", O_RDONLY | O_NOFOLLOW, 0); if (attrdirfd >= 0) { ret = solaris_list_xattr(attrdirfd, list, size); close(attrdirfd); @@ -581,7 +582,7 @@ int sys_lremovexattr (const char *path, const char *uname) return attr_remove(path, attrname, flags); #elif defined(HAVE_ATTROPEN) int ret = -1; - int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); + int attrdirfd = solaris_attropen(path, ".", O_RDONLY | O_NOFOLLOW, 0); if (attrdirfd >= 0) { ret = solaris_unlinkat(attrdirfd, name); close(attrdirfd); @@ -767,7 +768,7 @@ int sys_lsetxattr (const char *path, const char *uname, const void *value, size_ return attr_set(path, attrname, (const char *)value, size, myflags); #elif defined(HAVE_ATTROPEN) int ret = -1; - int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW; + int myflags = O_RDWR | O_NOFOLLOW; int attrfd; if (flags & XATTR_CREATE) myflags |= O_EXCL; if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; @@ -866,21 +867,43 @@ static int solaris_unlinkat(int attrdirfd, const char *name) static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode) { - int filedes; + EC_INIT; + int filedes = -1, eafd = -1; - if ((filedes = attropen(path, attrpath, oflag, mode)) == -1) { + if ((filedes = open(path, O_RDONLY | (oflag & O_NOFOLLOW), mode)) == -1) { switch (errno) { case ENOENT: case EEXIST: - break; + case OPEN_NOFOLLOW_ERRNO: + EC_FAIL; default: - LOG(log_debug, logtype_default, "attropen(\"%s\", ea:'%s'): %s", - path, attrpath, strerror(errno)); + LOG(log_debug, logtype_default, "open(\"%s\"): %s", fullpathname(path), strerror(errno)); errno = ENOATTR; - break; + EC_FAIL; } } - return filedes; + + if ((eafd = openat(filedes, attrpath, oflag | O_XATTR, mode)) == -1) { + switch (errno) { + case ENOENT: + case EEXIST: + EC_FAIL; + default: + LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno)); + errno = ENOATTR; + EC_FAIL; + } + } + +EC_CLEANUP: + if (filedes != -1) + close(filedes); + if (ret != 0) { + if (eafd != -1) + close(eafd); + eafd = -1; + } + return eafd; } static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode) -- 2.39.2