Hao Xu wrote:
> KaiGai Kohei wrote:
>> Hao,
>> I also recommend you to make a small patch to fix a bug you noticed. :)
>>   
> The fix is trivial, you can easily include it in your patch.

libcap-1.10-fix-cap_from_text.patch fixes the bug you noticed.
# It is not preferred to merge several purposes into a single patch
# in generally, so I separated them into two patches.

> BTW, you may want to remove all the Japanese characters in your patch.

I removed them. See, libcap-1.10-vfscaps.2.patch.

Thanks,
-- 
Open Source Software Promotion Center, NEC
KaiGai Kohei <[EMAIL PROTECTED]>
Index: libcap-1.10.kg/doc/getfcaps.8
===================================================================
--- libcap-1.10.kg/doc/getfcaps.8	(revision 0)
+++ libcap-1.10.kg/doc/getfcaps.8	(revision 4)
@@ -0,0 +1 @@
+.so man8/setfcaps.8
Index: libcap-1.10.kg/doc/setfcaps.8
===================================================================
--- libcap-1.10.kg/doc/setfcaps.8	(revision 0)
+++ libcap-1.10.kg/doc/setfcaps.8	(revision 4)
@@ -0,0 +1,38 @@
+.\"
+.\" $Id: setcap.8,v 1.1.1.1 1999/04/17 22:16:31 morgan Exp $
+.\"
+.TH SETCAP 8 "7th Nov 2006"
+.SH NAME
+setfcaps/getfcaps \- set/get file capabilities
+.SH SYNOPSIS
+\fBsetfcaps\fP \fI<capabilities>\fP [ \fIfilenames ...\fP ]
+
+\fBgetfcaps\fP [\fB-rvh\fP] [ \fIfilenames ...\fP ]
+.SH DESCRIPTION
+.B setfcaps
+sets the capabilities of each specified
+.I filename
+to the
+.I capabilities
+specified.  The
+.I capabilities
+are specified in the form described in
+.IR cap_from_text (3).
+.PP
+.B getfcaps
+prints the capabilities of each specified
+.I filenames
+. You can specify
+.B -r
+option to list subdirectories recursively.
+When
+.B -v
+option was enabled, you can also confirm that the specified
+.I filenames
+have no capabilities.
+.SH "AUTHOR"
+This program was written by KaiGai Kohei <[EMAIL PROTECTED]>
+.SH "SEE ALSO"
+.IR cap_from_text (3),
+.IR cap_set_file (3),
+.IR cap_get_file (3)
Index: libcap-1.10.kg/libcap/_makenames.c
===================================================================
--- libcap-1.10.kg/libcap/_makenames.c	(revision 1)
+++ libcap-1.10.kg/libcap/_makenames.c	(revision 4)
@@ -45,6 +45,7 @@
 	   "#define __CAP_BITS   %d\n"
 	   "\n"
 	   "#ifdef LIBCAP_PLEASE_INCLUDE_ARRAY\n"
+	   "  int const _cap_names_num = __CAP_BITS;\n"
 	   "  char const *_cap_names[__CAP_BITS] = {\n", maxcaps);
 
     for (i=0; i<maxcaps; ++i) {
Index: libcap-1.10.kg/libcap/cap_file.c
===================================================================
--- libcap-1.10.kg/libcap/cap_file.c	(revision 1)
+++ libcap-1.10.kg/libcap/cap_file.c	(revision 4)
@@ -10,6 +10,92 @@
 
 #include "libcap.h"
 
+#include <endian.h>
+#include <byteswap.h>
+#include <attr/xattr.h>
+
+#define VFS_CAPABILITY_XNAME  "security.capability"
+struct vfs_cap_data_struct {
+    __u32 version;  /* = _LINUX_CAPABILITY_VERSION */
+    __u32 effective;
+    __u32 permitted;
+    __u32 inheritable;
+};
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define le32_to_cpu(x)  x
+#define le16_to_cpu(x)  x
+#define cpu_to_le32(x)  x
+#define cpu_to_le16(x)  x
+#elif
+#define le32_to_cpu(x)  bswap_32(x)
+#define le16_to_cpu(x)  bswap_16(x)
+#define cpu_to_le32(x)  bswap_32(x)
+#define cpu_to_le16(x)  bswap_16(x)
+#endif
+
+static inline int __getfilecap(struct vfs_cap_data_struct *xdata, int rc, cap_user_data_t ucaps)
+{
+    if (rc != sizeof(struct vfs_cap_data_struct)) {
+	if (errno == ENODATA) {
+	    ucaps->effective = 0;
+	    ucaps->permitted = 0;
+	    ucaps->inheritable = 0;
+	    return 0;
+	}
+	return 1;
+    }
+
+    if (le32_to_cpu(xdata->version) != _LINUX_CAPABILITY_VERSION) {
+	_cap_debug("file capability version mismatching");
+	return 1;
+    }
+    ucaps->effective = le32_to_cpu(xdata->effective);
+    ucaps->permitted = le32_to_cpu(xdata->permitted);
+    ucaps->inheritable = le32_to_cpu(xdata->inheritable);
+    return 0;
+}
+
+static int _fgetfilecap(int fildes, cap_user_data_t ucaps)
+{
+    struct vfs_cap_data_struct xdata;
+    int rc;
+
+    rc = fgetxattr(fildes, VFS_CAPABILITY_XNAME, &xdata, sizeof(xdata));
+    return __getfilecap(&xdata, rc, ucaps);
+}
+
+static int _getfilecap(const char *fname, cap_user_data_t ucaps)
+{
+    struct vfs_cap_data_struct xdata;
+    int rc;
+
+    rc = getxattr(fname, VFS_CAPABILITY_XNAME, &xdata, sizeof(xdata));
+    return __getfilecap(&xdata, rc, ucaps);
+}
+
+static int _fsetfilecap(int fildes, cap_user_data_t ucaps)
+{
+    struct vfs_cap_data_struct xdata;
+    
+    xdata.version = cpu_to_le32(_LINUX_CAPABILITY_VERSION);
+    xdata.inheritable = cpu_to_le32(ucaps->inheritable);
+    xdata.permitted = cpu_to_le32(ucaps->permitted);
+    xdata.effective = cpu_to_le32(ucaps->effective);
+    return fsetxattr(fildes, VFS_CAPABILITY_XNAME, &xdata, sizeof(xdata), 0);
+}
+
+static int _setfilecap(const char *fname, cap_user_data_t ucaps)
+{
+    struct vfs_cap_data_struct xdata;
+    
+    xdata.version = cpu_to_le32(_LINUX_CAPABILITY_VERSION);
+    xdata.inheritable = cpu_to_le32(ucaps->inheritable);
+    xdata.permitted = cpu_to_le32(ucaps->permitted);
+    xdata.effective = cpu_to_le32(ucaps->effective);
+    return setxattr(fname, VFS_CAPABILITY_XNAME, &xdata, sizeof(xdata), 0);
+}
+
 /*
  * Get the capabilities of an open file, as specified by its file
  * descriptor.
@@ -25,14 +111,9 @@
 	_cap_debug("getting fildes capabilities");
 
 	/* fill the capability sets via a system call */
-	if (_fgetfilecap(fildes, sizeof(struct __cap_s),
-			      &result->set[CAP_INHERITABLE],
-			      &result->set[CAP_PERMITTED],
-			      &result->set[CAP_EFFECTIVE] )) {
+	if (_fgetfilecap(fildes, &result->set))
 	    cap_free(&result);
-	}
     }
-
     return result;
 }
 
@@ -50,13 +131,9 @@
 	_cap_debug("getting named file capabilities");
 
 	/* fill the capability sets via a system call */
-	if (_getfilecap(filename, sizeof(struct __cap_s),
-			     &result->set[CAP_INHERITABLE],
-			     &result->set[CAP_PERMITTED],
-			     &result->set[CAP_EFFECTIVE] ))
+	if (_getfilecap(filename, &result->set))
 	    cap_free(&result);
     }
-
     return result;
 }
 
@@ -73,10 +150,7 @@
     }
 
     _cap_debug("setting fildes capabilities");
-    return _fsetfilecap(fildes, sizeof(struct __cap_s),
-			  &cap_d->set[CAP_INHERITABLE],
-			  &cap_d->set[CAP_PERMITTED],
-			  &cap_d->set[CAP_EFFECTIVE] );
+    return _fsetfilecap(fildes, &cap_d->set);
 }
 
 /*
@@ -91,10 +165,7 @@
     }
 
     _cap_debug("setting filename capabilities");
-    return _setfilecap(filename, sizeof(struct __cap_s),
-			  &cap_d->set[CAP_INHERITABLE],
-			  &cap_d->set[CAP_PERMITTED],
-			  &cap_d->set[CAP_EFFECTIVE] );
+    return _setfilecap(filename, &cap_d->set);
 }
 
 /*
Index: libcap-1.10.kg/libcap/include/sys/capability.h
===================================================================
--- libcap-1.10.kg/libcap/include/sys/capability.h	(revision 1)
+++ libcap-1.10.kg/libcap/include/sys/capability.h	(revision 4)
@@ -113,6 +113,7 @@
 extern int capgetp(pid_t pid, cap_t cap_d);
 extern int capsetp(pid_t pid, cap_t cap_d);
 extern char const *_cap_names[];
+extern int const _cap_names_num;
 
 #endif /* !defined(_POSIX_SOURCE) */
 
Index: libcap-1.10.kg/libcap/Makefile
===================================================================
--- libcap-1.10.kg/libcap/Makefile	(revision 1)
+++ libcap-1.10.kg/libcap/Makefile	(revision 4)
@@ -35,7 +35,7 @@
 FILES=cap_alloc cap_proc cap_extint cap_flag cap_text cap_sys
 
 # for later when there is filesystem support for cap's:
-#FILES += cap_file 
+FILES += cap_file 
 
 INCLS=libcap.h cap_names.h $(INCS)
 OBJS=$(addsuffix .o, $(FILES))
Index: libcap-1.10.kg/progs/setfcaps.c
===================================================================
--- libcap-1.10.kg/progs/setfcaps.c	(revision 0)
+++ libcap-1.10.kg/progs/setfcaps.c	(revision 4)
@@ -0,0 +1,52 @@
+/*
+ * setfcap - Configuration tool for XATTR based VFS capability support.
+ *
+ * Author:      KaiGai Kohei <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modidy
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <error.h>
+#include <errno.h>
+#include <sys/capability.h>
+
+extern int const _cap_names_num;
+extern char const *_cap_names[];
+
+static void usage() {
+    const char *message = "usage: setfcaps <capabilities> <file> ...";
+    int i;
+
+    fputs(message, stderr);
+    for (i=0; i < _cap_names_num; i++)
+        fprintf(stderr, "%s%s", i%4==0 ? "\n\t" : ", ", _cap_names[i]);
+    fputc('\n', stderr);
+    exit(0);
+}
+
+int main(int argc, char *argv[]) {
+    cap_t caps;
+    int rc, i;
+
+    if (argc < 3)
+	usage();
+
+    caps = cap_from_text(argv[1]);
+    if (!caps) {
+	printf("invalid capabilities: %s\n", argv[1]);
+	return 1;
+    }
+
+    for (i=2; i<argc; i++) {
+	rc = cap_set_file(argv[i], caps);
+	if (rc)
+	    printf("%s: %s (errno=%d)\n", argv[i], strerror(errno), errno);
+    }
+    cap_free(caps);
+
+    return 0;
+}
Index: libcap-1.10.kg/progs/Makefile
===================================================================
--- libcap-1.10.kg/progs/Makefile	(revision 1)
+++ libcap-1.10.kg/progs/Makefile	(revision 4)
@@ -31,7 +31,7 @@
 PROGS=getpcaps setpcaps execcap sucap
 
 # when we have filecaps...
-#PROGS+=getcap setcap
+PROGS += getfcaps setfcaps
 
 all: $(PROGS)
 
Index: libcap-1.10.kg/progs/getfcaps.c
===================================================================
--- libcap-1.10.kg/progs/getfcaps.c	(revision 0)
+++ libcap-1.10.kg/progs/getfcaps.c	(revision 4)
@@ -0,0 +1,101 @@
+/*
+ * getfcap - Configuration tool for XATTR based VFS capability support.
+ *
+ * Author:      KaiGai Kohei <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modidy
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/capability.h>
+#include <linux/limits.h>
+
+static int recursive = 0;
+static int verbose = 0;
+
+static void usage() {
+    const char *message = "usage: getfcaps [-rvh] <file> ...\n"
+	"\t-r : recursive search\n"
+	"\t-v : verbose mode\n"
+	"\t-h : show this message\n";
+    fputs(message, stderr);
+    exit(1);
+}
+
+static void __getfcaps_dir(const char *fname);
+
+static void do_getfcaps(const char *fname) {
+    struct stat st_buf;
+    cap_t caps;
+
+    if (stat(fname, &st_buf)) {
+	if (verbose)
+	    printf("%s\n", fname);
+	return;
+    }
+
+    if (S_ISREG(st_buf.st_mode)) {
+	ssize_t length;
+	char *cap_name;
+	caps = cap_get_file(fname);
+	cap_name = cap_to_text(caps, &length);
+	if (verbose || strcmp("=",cap_name))
+	    printf("%s %s\n", fname, cap_name ? cap_name : "");
+	cap_free(caps);
+    } else if (recursive && S_ISDIR(st_buf.st_mode)) {
+	__getfcaps_dir(fname);
+    } else if (verbose) {
+	printf("%s\n", fname);
+    }
+}
+
+static void __getfcaps_dir(const char *fname) {
+    DIR *dirp;
+    struct dirent *dent;
+    char buffer[PATH_MAX];
+    
+    dirp = opendir(fname);
+    if (!dirp) {
+	if (verbose)
+	    printf("%s: \n", fname);
+	return;
+    }
+    
+    while ((dent = readdir(dirp))) {
+	if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+	    continue;
+	snprintf(buffer, PATH_MAX, "%s/%s", fname, dent->d_name);
+	do_getfcaps(buffer);
+    }
+    closedir(dirp);
+}
+
+int main(int argc, char *argv[]) {
+    int i, c;
+
+    while ((c = getopt(argc, argv, "rvh")) > 0) {
+	switch (c) {
+	case 'r':
+	    recursive = 1;
+	    break;
+	case 'v':
+	    verbose = 1;
+	    break;
+	default:
+	    usage();
+	}
+    }
+    if (!argv[optind])
+	usage();
+    for (i = optind; i < argc; i++)
+	do_getfcaps(argv[i]);
+    return 0;
+}
diff -prNU3 libcap-1.10/libcap/cap_text.c libcap-1.10.fixed/libcap/cap_text.c
--- libcap-1.10/libcap/cap_text.c	1999-11-18 15:03:26.000000000 +0900
+++ libcap-1.10.fixed/libcap/cap_text.c	2007-04-12 16:54:44.000000000 +0900
@@ -209,7 +209,7 @@ cap_t cap_from_text(const char *str)
     }
 
 bad:
-    cap_free(&res);
+    cap_free(res);
     errno = EINVAL;
     return NULL;
 }

Reply via email to