Filesystem capabilities are only meaningful on regular files.

Do not support putting capabilies on symlinks and directories. You can
get around this with an older version of libcap, or using the raw
xattr API, but there is little point; the kernel only pays attention
to file capabilities when it exec()s a file.

Bug report: Chris Friedhoff
Suggested fix: Serge E. Hallyn
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
diff --git a/Make.Rules b/Make.Rules
index 2014f38..0ffabe4 100644
--- a/Make.Rules
+++ b/Make.Rules
@@ -41,7 +41,7 @@
 # common defines for libcap
 LIBTITLE=libcap
 VERSION=2
-MINOR=03
+MINOR=04
 #
 
 # Compilation specifics
diff --git a/libcap/cap_file.c b/libcap/cap_file.c
index d7a2da7..c025bf5 100644
--- a/libcap/cap_file.c
+++ b/libcap/cap_file.c
@@ -7,6 +7,8 @@
 #include <sys/types.h>
 #include <attr/xattr.h>
 #include <byteswap.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #define XATTR_SECURITY_PREFIX "security."
 
@@ -227,6 +229,17 @@
 {
     struct vfs_cap_data rawvfscap;
     int sizeofcaps;
+    struct stat buf;
+
+    if (fstat(fildes, &buf) != 0) {
+	_cap_debug("unable to stat file descriptor %d", fildes);
+	return -1;
+    }
+    if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
+	_cap_debug("file descriptor %d for non-regular file", fildes);
+	errno = EINVAL;
+	return -1;
+    }
 
     if (cap_d == NULL) {
 	_cap_debug("deleting fildes capabilities");
@@ -248,6 +261,17 @@
 {
     struct vfs_cap_data rawvfscap;
     int sizeofcaps;
+    struct stat buf;
+
+    if (lstat(filename, &buf) != 0) {
+	_cap_debug("unable to stat file [%s]", filename);
+	return -1;
+    }
+    if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
+	_cap_debug("file [%s] is not a regular file", filename);
+	errno = EINVAL;
+	return -1;
+    }
 
     if (cap_d == NULL) {
 	_cap_debug("removing filename capabilities");
diff --git a/progs/setcap.c b/progs/setcap.c
index dc13c06..0501a9d 100644
--- a/progs/setcap.c
+++ b/progs/setcap.c
@@ -16,6 +16,8 @@
     fprintf(stderr,
 	    "usage: setcap [-q] (-r|-|<caps>) <filename> "
 	    "[ ... (-r|-|<capsN>) <filenameN> ]\n"
+	    "\n"
+	    " Note <filename> must be a regular (non-symlink) file.\n"
 	);
     exit(1);
 }