This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-daemon.git
The following commit(s) were added to refs/heads/master by this push:
new 5f0330e Fix DAEMON-426
5f0330e is described below
commit 5f0330e64c29349ffe469133f893e746b6ed141e
Author: Mark Thomas <[email protected]>
AuthorDate: Tue Dec 8 17:04:33 2020 +0000
Fix DAEMON-426
https://issues.apache.org/jira/projects/DAEMON/issues/DAEMON-426
Make the CAP_DAC_READ_SEARCH capability a nice to have rather than a
mandatory requirement.
---
src/changes/changes.xml | 5 ++
src/native/unix/native/jsvc-unix.c | 111 ++++++++++++++++++++++++-------------
2 files changed, 76 insertions(+), 40 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 31c5afa..6a4709d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -47,6 +47,11 @@
Procrun. Correct a regression introduced in 1.2.3. Enable the service
to
start if the Options value is not present in the registry.
</action>
+ <action issue="DAEMON-426" type="fix" dev="markt">
+ jsvc. Don't fail if the CAP_DAC_READ_SEARCH capability is not
available.
+ Fall back to using argv[0] rather than /proc/self/exe to determine the
+ path for the current binary.
+ </action>
</release>
<release version="1.2.3" date="2020-09-01" description="Bug fix release">
<action issue="DAEMON-411" type="fix" dev="markt">
diff --git a/src/native/unix/native/jsvc-unix.c
b/src/native/unix/native/jsvc-unix.c
index f7f90c4..d87554a 100644
--- a/src/native/unix/native/jsvc-unix.c
+++ b/src/native/unix/native/jsvc-unix.c
@@ -167,15 +167,23 @@ static int set_user_group(const char *user, int uid, int
gid)
/* Set linux capability, user and group */
#ifdef OS_LINUX
-/* That a more reasonable configuration */
-#define LEGACY_CAPS (1 << CAP_NET_BIND_SERVICE) + \
- (1 << CAP_DAC_READ_SEARCH) + \
- (1 << CAP_SETUID) + \
- (1 << CAP_SETGID)
+/* Preferred capabilities for getuid/setuid */
+#define LEGACY_CAPS_UID (1 << CAP_NET_BIND_SERVICE) + \
+ (1 << CAP_DAC_READ_SEARCH) + \
+ (1 << CAP_SETUID) + \
+ (1 << CAP_SETGID)
-/* probably the only one Java could use */
-#define LEGACY_CAPSMIN (1 << CAP_NET_BIND_SERVICE) + \
- (1 << CAP_DAC_READ_SEARCH)
+/* Minimum required capabilities for getuid/setuid */
+#define LEGACY_CAPS_UID_MIN (1 << CAP_NET_BIND_SERVICE) + \
+ (1 << CAP_SETUID) + \
+ (1 << CAP_SETGID)
+
+/* Preferred capabilities without getuid/setuid */
+#define LEGACY_CAPS_NO_UID (1 << CAP_NET_BIND_SERVICE) + \
+ (1 << CAP_DAC_READ_SEARCH)
+
+/* Minimum required capabilities without getuid/setuid */
+#define LEGACY_CAPS_NO_UID_MIN (1 << CAP_NET_BIND_SERVICE)
#define LEGACY_CAP_VERSION 0x19980330
static int set_legacy_caps(int caps)
@@ -199,20 +207,32 @@ static int set_legacy_caps(int caps)
}
#ifdef HAVE_LIBCAP
-static cap_value_t caps_std[] = {
+static cap_value_t caps_uid[] = {
CAP_NET_BIND_SERVICE,
CAP_SETUID,
CAP_SETGID,
CAP_DAC_READ_SEARCH
};
-static cap_value_t caps_min[] = {
+static cap_value_t caps_uid_min[] = {
+ CAP_NET_BIND_SERVICE,
+ CAP_SETUID,
+ CAP_SETGID
+};
+
+static cap_value_t caps_no_uid[] = {
CAP_NET_BIND_SERVICE,
CAP_DAC_READ_SEARCH
};
-#define CAPS 1
-#define CAPSMIN 2
+static cap_value_t caps_no_uid_min[] = {
+ CAP_NET_BIND_SERVICE
+};
+
+#define CAPS_UID 1
+#define CAPS_UID_MIN 2
+#define CAPS_NO_UID 3
+#define CAPS_NO_UID_MIN 4
typedef int (*fd_cap_free) (void *);
@@ -291,25 +311,29 @@ static int set_caps(int cap_type)
int ncap;
int flag = CAP_SET;
cap_value_t *caps;
- const char *type;
if (ld_libcap()) {
return set_legacy_caps(cap_type);
}
- if (cap_type == CAPS) {
- ncap = sizeof(caps_std) / sizeof(cap_value_t);
- caps = caps_std;
- type = "default";
+ if (cap_type == CAPS_UID) {
+ ncap = sizeof(caps_uid) / sizeof(cap_value_t);
+ caps = caps_uid;
}
- else if (cap_type == CAPSMIN) {
- ncap = sizeof(caps_min) / sizeof(cap_value_t);
- caps = caps_min;
- type = "min";
+ else if (cap_type == CAPS_UID_MIN) {
+ ncap = sizeof(caps_uid_min) / sizeof(cap_value_t);
+ caps = caps_uid_min;
+ }
+ else if (cap_type == CAPS_NO_UID) {
+ ncap = sizeof(caps_no_uid) / sizeof(cap_value_t);
+ caps = caps_no_uid;
+ }
+ else if (cap_type == CAPS_NO_UID_MIN) {
+ ncap = sizeof(caps_no_uid_min) / sizeof(cap_value_t);
+ caps = caps_no_uid_min;
}
else {
- ncap = sizeof(caps_min) / sizeof(cap_value_t);
- caps = caps_min;
- type = "null";
+ ncap = sizeof(caps_no_uid_min) / sizeof(cap_value_t);
+ caps = caps_no_uid_min;
flag = CAP_CLEAR;
}
c = (*fp_cap_init) ();
@@ -318,22 +342,23 @@ static int set_caps(int cap_type)
(*fp_cap_set_flag) (c, CAP_INHERITABLE, ncap, caps, flag);
(*fp_cap_set_flag) (c, CAP_PERMITTED, ncap, caps, flag);
if ((*fp_cap_set_proc) (c) != 0) {
- log_error("failed setting %s capabilities.", type);
return -1;
}
(*fp_cap_free) (c);
- if (cap_type == CAPS)
+ if (cap_type == CAPS_UID || cap_type == CAPS_UID_MIN)
log_debug("increased capability set.");
- else if (cap_type == CAPSMIN)
- log_debug("decreased capability set to min required.");
+ else if (cap_type == CAPS_NO_UID || cap_type == CAPS_NO_UID_MIN)
+ log_debug("decreased capability set.");
else
log_debug("dropped capabilities.");
return 0;
}
#else /* !HAVE_LIBCAP */
-#define CAPS LEGACY_CAPS
-#define CAPSMIN LEGACY_CAPSMIN
+#define CAPS_UID LEGACY_CAPS_UID
+#define CAPS_UID_MIN LEGACY_CAPS_UID_MIN
+#define CAPS_NO_UID LEGACY_CAPS_NO_UID
+#define CAPS_NO_UID_MIN LEGACY_CAPS_NO_UID
static int set_caps(int caps)
{
return set_legacy_caps(caps);
@@ -348,12 +373,15 @@ static int linuxset_user_group(const char *user, int uid,
int gid)
return 0;
/* set capabilities enough for binding port 80 setuid/getuid */
if (getuid() == 0) {
- if (set_caps(CAPS) != 0) {
- if (getuid() != uid) {
- log_error("set_caps(CAPS) failed for user '%s'", user);
- return -1;
+ if (set_caps(CAPS_UID) != 0) {
+ log_debug("set_caps(CAPS_UID) failed for user '%s'", user);
+ if (set_caps(CAPS_UID_MIN) != 0) {
+ if (getuid() != uid) {
+ log_error("set_caps(CAPS_UID_MIN) failed for user '%s'",
user);
+ return -1;
+ }
+ log_debug("set_caps(CAPS_UID_MIN) failed for user '%s'", user);
}
- log_debug("set_caps(CAPS) failed for user '%s'", user);
}
/* make sure they are kept after setuid */
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
@@ -371,12 +399,15 @@ static int linuxset_user_group(const char *user, int uid,
int gid)
if (caps_set) {
/* set capability to binding port 80 read conf */
- if (set_caps(CAPSMIN) != 0) {
- if (getuid() != uid) {
- log_error("set_caps(CAPSMIN) failed for user '%s'", user);
- return -1;
+ if (set_caps(CAPS_NO_UID) != 0) {
+ log_debug("set_caps(CAPS_NO_UID) failed for user '%s'", user);
+ if (set_caps(CAPS_NO_UID_MIN) != 0) {
+ if (getuid() != uid) {
+ log_error("set_caps(CAPS_NO_UID_MIN) failed for user
'%s'", user);
+ return -1;
+ }
+ log_debug("set_caps(CAPS_NO_UID_MIN) failed for user '%s'",
user);
}
- log_debug("set_caps(CAPSMIN) failed for user '%s'", user);
}
}