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;
}