Accepting request 888794 from network:samba:STABLE
- cifs.upcall: fix regression in kerberos mount; (bsc#1184815). * add 0001-cifs.upcall-fix-regression-in-kerberos-mount.patch - CVE-2021-20208: cifs-utils: cifs.upcall kerberos auth leak in container; (bsc#1183239); CVE-2021-20208. * add 0001-cifs.upcall-try-to-use-container-ipc-uts-net-pid-mnt.patch - Make cifs-idmap plugin (idmapwb.so) use update-alternatives mechanism to be able to switch between cifs-utils and sssd; (bsc#1182682). OBS-URL: https://build.opensuse.org/request/show/888794 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/cifs-utils?expand=0&rev=67
This commit is contained in:
commit
07c5d3dc0c
493
0001-cifs.upcall-fix-regression-in-kerberos-mount.patch
Normal file
493
0001-cifs.upcall-fix-regression-in-kerberos-mount.patch
Normal file
@ -0,0 +1,493 @@
|
|||||||
|
From 4ca235223d948fe4f3392da28b1471bce36e88d4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Aurelien Aptel <aaptel@suse.com>
|
||||||
|
Date: Wed, 21 Apr 2021 16:22:15 +0200
|
||||||
|
Subject: [PATCH v4] cifs.upcall: fix regression in kerberos mount
|
||||||
|
|
||||||
|
The fix for CVE-2021-20208 in commit e461afd ("cifs.upcall: try to use
|
||||||
|
container ipc/uts/net/pid/mnt/user namespaces") introduced a
|
||||||
|
regression for kerberos mounts when cifs-utils is built with
|
||||||
|
libcap-ng. It makes mount fail with ENOKEY "Required key not
|
||||||
|
available".
|
||||||
|
|
||||||
|
Current state:
|
||||||
|
|
||||||
|
mount.cifs
|
||||||
|
'---> mount() ---> kernel
|
||||||
|
negprot, session setup (need security blob for krb)
|
||||||
|
request_key("cifs.spnego", payload="pid=%d;username=...")
|
||||||
|
upcall
|
||||||
|
/sbin/request-key <--------------'
|
||||||
|
reads /etc/request-keys.conf
|
||||||
|
dispatch cifs.spnego request
|
||||||
|
calls /usr/sbin/cifs.upcall <key id>
|
||||||
|
- drop privileges (capabilities)
|
||||||
|
- fetch keyid
|
||||||
|
- parse payload
|
||||||
|
- switch to mount.cifs namespaces
|
||||||
|
- call krb5_xxx() funcs
|
||||||
|
- generate security blob
|
||||||
|
- set key value to security blob
|
||||||
|
'-----------------------------------> kernel
|
||||||
|
put blob in session setup packet
|
||||||
|
continue auth
|
||||||
|
open tcon
|
||||||
|
get share root
|
||||||
|
setup superblock
|
||||||
|
mount.cifs mount() returns <-----------'
|
||||||
|
|
||||||
|
By the time cifs.upcall tries to switch to namespaces, enough
|
||||||
|
capabilities have dropped in trim_capabilities() that it makes setns()
|
||||||
|
fail with EPERM.
|
||||||
|
|
||||||
|
setns() requires CAP_SYS_ADMIN.
|
||||||
|
|
||||||
|
With libcap trim_capabilities() is a no-op.
|
||||||
|
|
||||||
|
This fix:
|
||||||
|
|
||||||
|
- moves the namespace switch earlier so that operations like
|
||||||
|
setgroups(), setgid(), scanning of pid environment, ... happens in the
|
||||||
|
contained namespaces.
|
||||||
|
- moves trim_capabilities() after the namespace switch
|
||||||
|
- moves the string processing to decode the key request payload in a
|
||||||
|
child process with minimum capabilities. the decoded data is shared
|
||||||
|
with the parent process via shared memory obtained with mmap().
|
||||||
|
|
||||||
|
Fixes: e461afd ("cifs.upcall: try to use container ipc/uts/net/pid/mnt/user namespaces")
|
||||||
|
Signed-off-by: Aurelien Aptel <aaptel@suse.com>
|
||||||
|
---
|
||||||
|
cifs.upcall.c | 214 ++++++++++++++++++++++++++++++++------------------
|
||||||
|
1 file changed, 139 insertions(+), 75 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/cifs.upcall.c b/cifs.upcall.c
|
||||||
|
index e413934..ad04301 100644
|
||||||
|
--- a/cifs.upcall.c
|
||||||
|
+++ b/cifs.upcall.c
|
||||||
|
@@ -52,6 +52,9 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sched.h>
|
||||||
|
+#include <sys/mman.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include "data_blob.h"
|
||||||
|
#include "spnego.h"
|
||||||
|
@@ -787,6 +790,25 @@ handle_krb5_mech(const char *oid, const char *host, DATA_BLOB * secblob,
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+struct decoded_args {
|
||||||
|
+ int ver;
|
||||||
|
+ char hostname[NI_MAXHOST + 1];
|
||||||
|
+ char ip[NI_MAXHOST + 1];
|
||||||
|
+
|
||||||
|
+/* Max user name length. */
|
||||||
|
+#define MAX_USERNAME_SIZE 256
|
||||||
|
+ char username[MAX_USERNAME_SIZE + 1];
|
||||||
|
+
|
||||||
|
+ uid_t uid;
|
||||||
|
+ uid_t creduid;
|
||||||
|
+ pid_t pid;
|
||||||
|
+ sectype_t sec;
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Flags to keep track of what was provided
|
||||||
|
+ */
|
||||||
|
#define DKD_HAVE_HOSTNAME 0x1
|
||||||
|
#define DKD_HAVE_VERSION 0x2
|
||||||
|
#define DKD_HAVE_SEC 0x4
|
||||||
|
@@ -796,23 +818,13 @@ handle_krb5_mech(const char *oid, const char *host, DATA_BLOB * secblob,
|
||||||
|
#define DKD_HAVE_CREDUID 0x40
|
||||||
|
#define DKD_HAVE_USERNAME 0x80
|
||||||
|
#define DKD_MUSTHAVE_SET (DKD_HAVE_HOSTNAME|DKD_HAVE_VERSION|DKD_HAVE_SEC)
|
||||||
|
-
|
||||||
|
-struct decoded_args {
|
||||||
|
- int ver;
|
||||||
|
- char *hostname;
|
||||||
|
- char *ip;
|
||||||
|
- char *username;
|
||||||
|
- uid_t uid;
|
||||||
|
- uid_t creduid;
|
||||||
|
- pid_t pid;
|
||||||
|
- sectype_t sec;
|
||||||
|
+ int have;
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
-decode_key_description(const char *desc, struct decoded_args *arg)
|
||||||
|
+__decode_key_description(const char *desc, struct decoded_args *arg)
|
||||||
|
{
|
||||||
|
- int len;
|
||||||
|
- int retval = 0;
|
||||||
|
+ size_t len;
|
||||||
|
char *pos;
|
||||||
|
const char *tkn = desc;
|
||||||
|
|
||||||
|
@@ -826,13 +838,13 @@ decode_key_description(const char *desc, struct decoded_args *arg)
|
||||||
|
len = pos - tkn;
|
||||||
|
|
||||||
|
len -= 5;
|
||||||
|
- free(arg->hostname);
|
||||||
|
- arg->hostname = strndup(tkn + 5, len);
|
||||||
|
- if (arg->hostname == NULL) {
|
||||||
|
- syslog(LOG_ERR, "Unable to allocate memory");
|
||||||
|
+ if (len > sizeof(arg->hostname)-1) {
|
||||||
|
+ syslog(LOG_ERR, "host= value too long for buffer");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
- retval |= DKD_HAVE_HOSTNAME;
|
||||||
|
+ memset(arg->hostname, 0, sizeof(arg->hostname));
|
||||||
|
+ strncpy(arg->hostname, tkn + 5, len);
|
||||||
|
+ arg->have |= DKD_HAVE_HOSTNAME;
|
||||||
|
syslog(LOG_DEBUG, "host=%s", arg->hostname);
|
||||||
|
} else if (!strncmp(tkn, "ip4=", 4) || !strncmp(tkn, "ip6=", 4)) {
|
||||||
|
if (pos == NULL)
|
||||||
|
@@ -841,13 +853,13 @@ decode_key_description(const char *desc, struct decoded_args *arg)
|
||||||
|
len = pos - tkn;
|
||||||
|
|
||||||
|
len -= 4;
|
||||||
|
- free(arg->ip);
|
||||||
|
- arg->ip = strndup(tkn + 4, len);
|
||||||
|
- if (arg->ip == NULL) {
|
||||||
|
- syslog(LOG_ERR, "Unable to allocate memory");
|
||||||
|
+ if (len > sizeof(arg->ip)-1) {
|
||||||
|
+ syslog(LOG_ERR, "ip[46]= value too long for buffer");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
- retval |= DKD_HAVE_IP;
|
||||||
|
+ memset(arg->ip, 0, sizeof(arg->ip));
|
||||||
|
+ strncpy(arg->ip, tkn + 4, len);
|
||||||
|
+ arg->have |= DKD_HAVE_IP;
|
||||||
|
syslog(LOG_DEBUG, "ip=%s", arg->ip);
|
||||||
|
} else if (strncmp(tkn, "user=", 5) == 0) {
|
||||||
|
if (pos == NULL)
|
||||||
|
@@ -856,13 +868,13 @@ decode_key_description(const char *desc, struct decoded_args *arg)
|
||||||
|
len = pos - tkn;
|
||||||
|
|
||||||
|
len -= 5;
|
||||||
|
- free(arg->username);
|
||||||
|
- arg->username = strndup(tkn + 5, len);
|
||||||
|
- if (arg->username == NULL) {
|
||||||
|
- syslog(LOG_ERR, "Unable to allocate memory");
|
||||||
|
+ if (len > sizeof(arg->username)-1) {
|
||||||
|
+ syslog(LOG_ERR, "user= value too long for buffer");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
- retval |= DKD_HAVE_USERNAME;
|
||||||
|
+ memset(arg->username, 0, sizeof(arg->username));
|
||||||
|
+ strncpy(arg->username, tkn + 5, len);
|
||||||
|
+ arg->have |= DKD_HAVE_USERNAME;
|
||||||
|
syslog(LOG_DEBUG, "user=%s", arg->username);
|
||||||
|
} else if (strncmp(tkn, "pid=", 4) == 0) {
|
||||||
|
errno = 0;
|
||||||
|
@@ -873,13 +885,13 @@ decode_key_description(const char *desc, struct decoded_args *arg)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
syslog(LOG_DEBUG, "pid=%u", arg->pid);
|
||||||
|
- retval |= DKD_HAVE_PID;
|
||||||
|
+ arg->have |= DKD_HAVE_PID;
|
||||||
|
} else if (strncmp(tkn, "sec=", 4) == 0) {
|
||||||
|
if (strncmp(tkn + 4, "krb5", 4) == 0) {
|
||||||
|
- retval |= DKD_HAVE_SEC;
|
||||||
|
+ arg->have |= DKD_HAVE_SEC;
|
||||||
|
arg->sec = KRB5;
|
||||||
|
} else if (strncmp(tkn + 4, "mskrb5", 6) == 0) {
|
||||||
|
- retval |= DKD_HAVE_SEC;
|
||||||
|
+ arg->have |= DKD_HAVE_SEC;
|
||||||
|
arg->sec = MS_KRB5;
|
||||||
|
}
|
||||||
|
syslog(LOG_DEBUG, "sec=%d", arg->sec);
|
||||||
|
@@ -891,7 +903,7 @@ decode_key_description(const char *desc, struct decoded_args *arg)
|
||||||
|
strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
- retval |= DKD_HAVE_UID;
|
||||||
|
+ arg->have |= DKD_HAVE_UID;
|
||||||
|
syslog(LOG_DEBUG, "uid=%u", arg->uid);
|
||||||
|
} else if (strncmp(tkn, "creduid=", 8) == 0) {
|
||||||
|
errno = 0;
|
||||||
|
@@ -901,7 +913,7 @@ decode_key_description(const char *desc, struct decoded_args *arg)
|
||||||
|
strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
- retval |= DKD_HAVE_CREDUID;
|
||||||
|
+ arg->have |= DKD_HAVE_CREDUID;
|
||||||
|
syslog(LOG_DEBUG, "creduid=%u", arg->creduid);
|
||||||
|
} else if (strncmp(tkn, "ver=", 4) == 0) { /* if version */
|
||||||
|
errno = 0;
|
||||||
|
@@ -911,14 +923,56 @@ decode_key_description(const char *desc, struct decoded_args *arg)
|
||||||
|
strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
- retval |= DKD_HAVE_VERSION;
|
||||||
|
+ arg->have |= DKD_HAVE_VERSION;
|
||||||
|
syslog(LOG_DEBUG, "ver=%d", arg->ver);
|
||||||
|
}
|
||||||
|
if (pos == NULL)
|
||||||
|
break;
|
||||||
|
tkn = pos + 1;
|
||||||
|
} while (tkn);
|
||||||
|
- return retval;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static unsigned int
|
||||||
|
+decode_key_description(const char *desc, struct decoded_args **arg)
|
||||||
|
+{
|
||||||
|
+ pid_t pid;
|
||||||
|
+ pid_t rc;
|
||||||
|
+ int status;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Do all the decoding/string processing in a child process
|
||||||
|
+ * with low privileges.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ *arg = mmap(NULL, sizeof(struct decoded_args), PROT_READ | PROT_WRITE,
|
||||||
|
+ MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||||||
|
+ if (*arg == MAP_FAILED) {
|
||||||
|
+ syslog(LOG_ERR, "%s: mmap failed: %s", __func__, strerror(errno));
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pid = fork();
|
||||||
|
+ if (pid < 0) {
|
||||||
|
+ syslog(LOG_ERR, "%s: fork failed: %s", __func__, strerror(errno));
|
||||||
|
+ munmap(*arg, sizeof(struct decoded_args));
|
||||||
|
+ *arg = NULL;
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ if (pid == 0) {
|
||||||
|
+ /* do the parsing in child */
|
||||||
|
+ drop_all_capabilities();
|
||||||
|
+ exit(__decode_key_description(desc, *arg));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rc = waitpid(pid, &status, 0);
|
||||||
|
+ if (rc < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||||
|
+ munmap(*arg, sizeof(struct decoded_args));
|
||||||
|
+ *arg = NULL;
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setup_key(const key_serial_t key, const void *data, size_t datalen)
|
||||||
|
@@ -1098,7 +1152,7 @@ int main(const int argc, char *const argv[])
|
||||||
|
bool try_dns = false, legacy_uid = false , env_probe = true;
|
||||||
|
char *buf;
|
||||||
|
char hostbuf[NI_MAXHOST], *host;
|
||||||
|
- struct decoded_args arg;
|
||||||
|
+ struct decoded_args *arg = NULL;
|
||||||
|
const char *oid;
|
||||||
|
uid_t uid;
|
||||||
|
char *keytab_name = NULL;
|
||||||
|
@@ -1109,7 +1163,6 @@ int main(const int argc, char *const argv[])
|
||||||
|
const char *key_descr = NULL;
|
||||||
|
|
||||||
|
hostbuf[0] = '\0';
|
||||||
|
- memset(&arg, 0, sizeof(arg));
|
||||||
|
|
||||||
|
openlog(prog, 0, LOG_DAEMON);
|
||||||
|
|
||||||
|
@@ -1150,9 +1203,6 @@ int main(const int argc, char *const argv[])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (trim_capabilities(env_probe))
|
||||||
|
- goto out;
|
||||||
|
-
|
||||||
|
/* is there a key? */
|
||||||
|
if (argc <= optind) {
|
||||||
|
usage();
|
||||||
|
@@ -1178,6 +1228,10 @@ int main(const int argc, char *const argv[])
|
||||||
|
|
||||||
|
syslog(LOG_DEBUG, "key description: %s", buf);
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * If we are requested a simple DNS query, do it and exit
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
if (strncmp(buf, "cifs.resolver", sizeof("cifs.resolver") - 1) == 0)
|
||||||
|
key_descr = ".cifs.resolver";
|
||||||
|
else if (strncmp(buf, "dns_resolver", sizeof("dns_resolver") - 1) == 0)
|
||||||
|
@@ -1187,33 +1241,42 @@ int main(const int argc, char *const argv[])
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- have = decode_key_description(buf, &arg);
|
||||||
|
+ /*
|
||||||
|
+ * Otherwise, it's a spnego key request
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ rc = decode_key_description(buf, &arg);
|
||||||
|
free(buf);
|
||||||
|
- if ((have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {
|
||||||
|
+ if (rc) {
|
||||||
|
+ syslog(LOG_ERR, "failed to decode key description");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((arg->have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {
|
||||||
|
syslog(LOG_ERR, "unable to get necessary params from key "
|
||||||
|
"description (0x%x)", have);
|
||||||
|
rc = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (arg.ver > CIFS_SPNEGO_UPCALL_VERSION) {
|
||||||
|
+ if (arg->ver > CIFS_SPNEGO_UPCALL_VERSION) {
|
||||||
|
syslog(LOG_ERR, "incompatible kernel upcall version: 0x%x",
|
||||||
|
- arg.ver);
|
||||||
|
+ arg->ver);
|
||||||
|
rc = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (strlen(arg.hostname) >= NI_MAXHOST) {
|
||||||
|
+ if (strlen(arg->hostname) >= NI_MAXHOST) {
|
||||||
|
syslog(LOG_ERR, "hostname provided by kernel is too long");
|
||||||
|
rc = 1;
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!legacy_uid && (have & DKD_HAVE_CREDUID))
|
||||||
|
- uid = arg.creduid;
|
||||||
|
- else if (have & DKD_HAVE_UID)
|
||||||
|
- uid = arg.uid;
|
||||||
|
+ if (!legacy_uid && (arg->have & DKD_HAVE_CREDUID))
|
||||||
|
+ uid = arg->creduid;
|
||||||
|
+ else if (arg->have & DKD_HAVE_UID)
|
||||||
|
+ uid = arg->uid;
|
||||||
|
else {
|
||||||
|
/* no uid= or creduid= parm -- something is wrong */
|
||||||
|
syslog(LOG_ERR, "No uid= or creduid= parm specified");
|
||||||
|
@@ -1221,6 +1284,21 @@ int main(const int argc, char *const argv[])
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Change to the process's namespace. This means that things will work
|
||||||
|
+ * acceptably in containers, because we'll be looking at the correct
|
||||||
|
+ * filesystem and have the correct network configuration.
|
||||||
|
+ */
|
||||||
|
+ rc = switch_to_process_ns(arg->pid);
|
||||||
|
+ if (rc == -1) {
|
||||||
|
+ syslog(LOG_ERR, "unable to switch to process namespace: %s", strerror(errno));
|
||||||
|
+ rc = 1;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (trim_capabilities(env_probe))
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* The kernel doesn't pass down the gid, so we resort here to scraping
|
||||||
|
* one out of the passwd nss db. Note that this might not reflect the
|
||||||
|
@@ -1266,20 +1344,7 @@ int main(const int argc, char *const argv[])
|
||||||
|
* look at the environ file.
|
||||||
|
*/
|
||||||
|
env_cachename =
|
||||||
|
- get_cachename_from_process_env(env_probe ? arg.pid : 0);
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * Change to the process's namespace. This means that things will work
|
||||||
|
- * acceptably in containers, because we'll be looking at the correct
|
||||||
|
- * filesystem and have the correct network configuration.
|
||||||
|
- */
|
||||||
|
- rc = switch_to_process_ns(arg.pid);
|
||||||
|
- if (rc == -1) {
|
||||||
|
- syslog(LOG_ERR, "unable to switch to process namespace: %s",
|
||||||
|
- strerror(errno));
|
||||||
|
- rc = 1;
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
+ get_cachename_from_process_env(env_probe ? arg->pid : 0);
|
||||||
|
|
||||||
|
rc = setuid(uid);
|
||||||
|
if (rc == -1) {
|
||||||
|
@@ -1301,18 +1366,18 @@ int main(const int argc, char *const argv[])
|
||||||
|
|
||||||
|
ccache = get_existing_cc(env_cachename);
|
||||||
|
/* Couldn't find credcache? Try to use keytab */
|
||||||
|
- if (ccache == NULL && arg.username != NULL)
|
||||||
|
- ccache = init_cc_from_keytab(keytab_name, arg.username);
|
||||||
|
+ if (ccache == NULL && arg->username[0] != '\0')
|
||||||
|
+ ccache = init_cc_from_keytab(keytab_name, arg->username);
|
||||||
|
|
||||||
|
if (ccache == NULL) {
|
||||||
|
rc = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- host = arg.hostname;
|
||||||
|
+ host = arg->hostname;
|
||||||
|
|
||||||
|
// do mech specific authorization
|
||||||
|
- switch (arg.sec) {
|
||||||
|
+ switch (arg->sec) {
|
||||||
|
case MS_KRB5:
|
||||||
|
case KRB5:
|
||||||
|
/*
|
||||||
|
@@ -1328,7 +1393,7 @@ int main(const int argc, char *const argv[])
|
||||||
|
* TRY only:
|
||||||
|
* cifs/bar.example.com@REALM
|
||||||
|
*/
|
||||||
|
- if (arg.sec == MS_KRB5)
|
||||||
|
+ if (arg->sec == MS_KRB5)
|
||||||
|
oid = OID_KERBEROS5_OLD;
|
||||||
|
else
|
||||||
|
oid = OID_KERBEROS5;
|
||||||
|
@@ -1385,10 +1450,10 @@ retry_new_hostname:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!try_dns || !(have & DKD_HAVE_IP))
|
||||||
|
+ if (!try_dns || !(arg->have & DKD_HAVE_IP))
|
||||||
|
break;
|
||||||
|
|
||||||
|
- rc = ip_to_fqdn(arg.ip, hostbuf, sizeof(hostbuf));
|
||||||
|
+ rc = ip_to_fqdn(arg->ip, hostbuf, sizeof(hostbuf));
|
||||||
|
if (rc)
|
||||||
|
break;
|
||||||
|
|
||||||
|
@@ -1396,7 +1461,7 @@ retry_new_hostname:
|
||||||
|
host = hostbuf;
|
||||||
|
goto retry_new_hostname;
|
||||||
|
default:
|
||||||
|
- syslog(LOG_ERR, "sectype: %d is not implemented", arg.sec);
|
||||||
|
+ syslog(LOG_ERR, "sectype: %d is not implemented", arg->sec);
|
||||||
|
rc = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -1414,7 +1479,7 @@ retry_new_hostname:
|
||||||
|
rc = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- keydata->version = arg.ver;
|
||||||
|
+ keydata->version = arg->ver;
|
||||||
|
keydata->flags = 0;
|
||||||
|
keydata->sesskey_len = sess_key.length;
|
||||||
|
keydata->secblob_len = secblob.length;
|
||||||
|
@@ -1440,11 +1505,10 @@ out:
|
||||||
|
krb5_cc_close(context, ccache);
|
||||||
|
if (context)
|
||||||
|
krb5_free_context(context);
|
||||||
|
- free(arg.hostname);
|
||||||
|
- free(arg.ip);
|
||||||
|
- free(arg.username);
|
||||||
|
free(keydata);
|
||||||
|
free(env_cachename);
|
||||||
|
+ if (arg)
|
||||||
|
+ munmap(arg, sizeof(*arg));
|
||||||
|
syslog(LOG_DEBUG, "Exit status %ld", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.30.0
|
||||||
|
|
264
0001-cifs.upcall-try-to-use-container-ipc-uts-net-pid-mnt.patch
Normal file
264
0001-cifs.upcall-try-to-use-container-ipc-uts-net-pid-mnt.patch
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
From e461afd8cfa6d0781ae0c5c10e89b6ef1ca6da32 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alastair Houghton <alastair@alastairs-place.net>
|
||||||
|
Date: Tue, 29 Dec 2020 14:02:39 +0000
|
||||||
|
Subject: [PATCH] cifs.upcall: try to use container ipc/uts/net/pid/mnt/user
|
||||||
|
namespaces
|
||||||
|
|
||||||
|
In certain scenarios (e.g. kerberos multimount), when a process does
|
||||||
|
syscalls, the kernel sometimes has to query information or trigger
|
||||||
|
some actions in userspace. To do so it calls the cifs.upcall binary
|
||||||
|
with information on the process that triggered the syscall in the
|
||||||
|
first place.
|
||||||
|
|
||||||
|
ls(pid=10) ====> open("foo") ====> kernel
|
||||||
|
|
||||||
|
that user doesn't have an SMB
|
||||||
|
session, lets create one using his
|
||||||
|
kerberos credential cache
|
||||||
|
|
||||||
|
call cifs.upcall and ask for krb info
|
||||||
|
for whoever owns pid=10
|
||||||
|
|
|
||||||
|
cifs.upcall --pid 10 <=================+
|
||||||
|
|
||||||
|
...gather info...
|
||||||
|
return binary blob used
|
||||||
|
when establishing SMB session
|
||||||
|
===================> kernel
|
||||||
|
open SMB session, handle
|
||||||
|
open() syscall
|
||||||
|
ls <=================================== return open() result to ls
|
||||||
|
|
||||||
|
On a system using containers, the kernel is still calling the host
|
||||||
|
cifs.upcall and using the host configuration (for network, pid, etc).
|
||||||
|
|
||||||
|
This patch changes the behaviour of cifs.upcall so that it uses the
|
||||||
|
calling process namespaces (ls in the example) when doing its
|
||||||
|
job.
|
||||||
|
|
||||||
|
Note that the kernel still calls the binary in the host, but the
|
||||||
|
binary will place itself the contexts of the calling process
|
||||||
|
namespaces.
|
||||||
|
|
||||||
|
This code makes use of (but shouldn't require) the following kernel
|
||||||
|
config options and syscall flags:
|
||||||
|
|
||||||
|
approx. year |
|
||||||
|
introduced | config/flags
|
||||||
|
---------------+----------------
|
||||||
|
2008 | CONFIG_NAMESPACES=y
|
||||||
|
2007 | CONFIG_UTS_NS=y
|
||||||
|
2020 | CONFIG_TIME_NS=y
|
||||||
|
2006 | CONFIG_IPC_NS=y
|
||||||
|
2007 | CONFIG_USER_NS
|
||||||
|
2008 | CONFIG_PID_NS=y
|
||||||
|
2007 | CONFIG_NET_NS=y
|
||||||
|
2007 | CONFIG_CGROUPS
|
||||||
|
2016 | CLONE_NEWCGROUP setns() flag
|
||||||
|
|
||||||
|
Signed-off-by: Aurelien Aptel <aaptel@suse.com>
|
||||||
|
Signed-off-by: Alastair Houghton <alastair@alastairs-place.net>
|
||||||
|
---
|
||||||
|
cifs.upcall.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 172 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/cifs.upcall.c b/cifs.upcall.c
|
||||||
|
index 400b42d..e413934 100644
|
||||||
|
--- a/cifs.upcall.c
|
||||||
|
+++ b/cifs.upcall.c
|
||||||
|
@@ -51,6 +51,7 @@
|
||||||
|
#include <grp.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <errno.h>
|
||||||
|
+#include <sched.h>
|
||||||
|
|
||||||
|
#include "data_blob.h"
|
||||||
|
#include "spnego.h"
|
||||||
|
@@ -240,6 +241,164 @@ err_cache:
|
||||||
|
return credtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static struct namespace_file {
|
||||||
|
+ int nstype;
|
||||||
|
+ const char *name;
|
||||||
|
+ int fd;
|
||||||
|
+} namespace_files[] = {
|
||||||
|
+
|
||||||
|
+#ifdef CLONE_NEWCGROUP
|
||||||
|
+ { CLONE_NEWCGROUP, "cgroup", -1 },
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef CLONE_NEWIPC
|
||||||
|
+ { CLONE_NEWIPC, "ipc", -1 },
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef CLONE_NEWUTS
|
||||||
|
+ { CLONE_NEWUTS, "uts", -1 },
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef CLONE_NEWNET
|
||||||
|
+ { CLONE_NEWNET, "net", -1 },
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef CLONE_NEWPID
|
||||||
|
+ { CLONE_NEWPID, "pid", -1 },
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef CLONE_NEWTIME
|
||||||
|
+ { CLONE_NEWTIME, "time", -1 },
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef CLONE_NEWNS
|
||||||
|
+ { CLONE_NEWNS, "mnt", -1 },
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef CLONE_NEWUSER
|
||||||
|
+ { CLONE_NEWUSER, "user", -1 },
|
||||||
|
+#endif
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#define NS_PATH_FMT "/proc/%d/ns/%s"
|
||||||
|
+#define NS_PATH_MAXLEN (6 + 10 + 4 + 6 + 1)
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * in_same_user_ns - return true if two processes are in the same user
|
||||||
|
+ * namespace.
|
||||||
|
+ * @pid_a: the pid of the first process
|
||||||
|
+ * @pid_b: the pid of the second process
|
||||||
|
+ *
|
||||||
|
+ * Works by comparing the inode numbers for /proc/<pid>/user.
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+in_same_user_ns(pid_t pid_a, pid_t pid_b)
|
||||||
|
+{
|
||||||
|
+ char path[NS_PATH_MAXLEN];
|
||||||
|
+ ino_t a_ino, b_ino;
|
||||||
|
+ struct stat st;
|
||||||
|
+
|
||||||
|
+ snprintf(path, sizeof(path), NS_PATH_FMT, pid_a, "user");
|
||||||
|
+ if (stat(path, &st) != 0)
|
||||||
|
+ return 0;
|
||||||
|
+ a_ino = st.st_ino;
|
||||||
|
+
|
||||||
|
+ snprintf(path, sizeof(path), NS_PATH_FMT, pid_b, "user");
|
||||||
|
+ if (stat(path, &st) != 0)
|
||||||
|
+ return 0;
|
||||||
|
+ b_ino = st.st_ino;
|
||||||
|
+
|
||||||
|
+ return a_ino == b_ino;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * switch_to_process_ns - change the namespace to the one for the specified
|
||||||
|
+ * process.
|
||||||
|
+ * @pid: initiating pid value from the upcall string
|
||||||
|
+ *
|
||||||
|
+ * Uses setns() to switch process namespace.
|
||||||
|
+ * This ensures that we have the same access and configuration as the
|
||||||
|
+ * process that triggered the lookup.
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+switch_to_process_ns(pid_t pid)
|
||||||
|
+{
|
||||||
|
+ int count = sizeof(namespace_files) / sizeof(struct namespace_file);
|
||||||
|
+ int n, err = 0;
|
||||||
|
+ int rc = 0;
|
||||||
|
+
|
||||||
|
+ /* First, open all the namespace fds. We do this first because
|
||||||
|
+ the namespace changes might prohibit us from opening them. */
|
||||||
|
+ for (n = 0; n < count; ++n) {
|
||||||
|
+ char nspath[NS_PATH_MAXLEN];
|
||||||
|
+ int ret, fd;
|
||||||
|
+
|
||||||
|
+#ifdef CLONE_NEWUSER
|
||||||
|
+ if (namespace_files[n].nstype == CLONE_NEWUSER
|
||||||
|
+ && in_same_user_ns(getpid(), pid)) {
|
||||||
|
+ /* Switching to the same user namespace is forbidden,
|
||||||
|
+ because switching to a user namespace grants all
|
||||||
|
+ capabilities in that namespace regardless of uid. */
|
||||||
|
+ namespace_files[n].fd = -1;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ ret = snprintf(nspath, NS_PATH_MAXLEN, NS_PATH_FMT,
|
||||||
|
+ pid, namespace_files[n].name);
|
||||||
|
+ if (ret >= NS_PATH_MAXLEN) {
|
||||||
|
+ syslog(LOG_DEBUG, "%s: unterminated path!\n", __func__);
|
||||||
|
+ err = ENAMETOOLONG;
|
||||||
|
+ rc = -1;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fd = open(nspath, O_RDONLY);
|
||||||
|
+ if (fd < 0 && errno != ENOENT) {
|
||||||
|
+ /*
|
||||||
|
+ * don't stop on non-existing ns
|
||||||
|
+ * but stop for other errors
|
||||||
|
+ */
|
||||||
|
+ err = errno;
|
||||||
|
+ rc = -1;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ namespace_files[n].fd = fd;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Next, call setns for each of them */
|
||||||
|
+ for (n = 0; n < count; ++n) {
|
||||||
|
+ /* skip non-existing ns */
|
||||||
|
+ if (namespace_files[n].fd < 0)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ rc = setns(namespace_files[n].fd, namespace_files[n].nstype);
|
||||||
|
+
|
||||||
|
+ if (rc < 0) {
|
||||||
|
+ syslog(LOG_DEBUG, "%s: setns() failed for %s\n",
|
||||||
|
+ __func__, namespace_files[n].name);
|
||||||
|
+ err = errno;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ /* Finally, close all the fds */
|
||||||
|
+ for (n = 0; n < count; ++n) {
|
||||||
|
+ if (namespace_files[n].fd != -1) {
|
||||||
|
+ close(namespace_files[n].fd);
|
||||||
|
+ namespace_files[n].fd = -1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (rc != 0) {
|
||||||
|
+ errno = err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#define ENV_PATH_FMT "/proc/%d/environ"
|
||||||
|
#define ENV_PATH_MAXLEN (6 + 10 + 8 + 1)
|
||||||
|
|
||||||
|
@@ -1109,6 +1268,19 @@ int main(const int argc, char *const argv[])
|
||||||
|
env_cachename =
|
||||||
|
get_cachename_from_process_env(env_probe ? arg.pid : 0);
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Change to the process's namespace. This means that things will work
|
||||||
|
+ * acceptably in containers, because we'll be looking at the correct
|
||||||
|
+ * filesystem and have the correct network configuration.
|
||||||
|
+ */
|
||||||
|
+ rc = switch_to_process_ns(arg.pid);
|
||||||
|
+ if (rc == -1) {
|
||||||
|
+ syslog(LOG_ERR, "unable to switch to process namespace: %s",
|
||||||
|
+ strerror(errno));
|
||||||
|
+ rc = 1;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
rc = setuid(uid);
|
||||||
|
if (rc == -1) {
|
||||||
|
syslog(LOG_ERR, "setuid: %s", strerror(errno));
|
||||||
|
--
|
||||||
|
2.30.0
|
||||||
|
|
@ -1,3 +1,16 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Apr 23 10:41:59 UTC 2021 - Aurelien Aptel <aaptel@suse.com>
|
||||||
|
|
||||||
|
- cifs.upcall: fix regression in kerberos mount; (bsc#1184815).
|
||||||
|
* add 0001-cifs.upcall-fix-regression-in-kerberos-mount.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Mar 9 17:17:59 UTC 2021 - palcantara@suse.de
|
||||||
|
|
||||||
|
- CVE-2021-20208: cifs-utils: cifs.upcall kerberos auth leak in
|
||||||
|
container; (bsc#1183239); CVE-2021-20208.
|
||||||
|
* add 0001-cifs.upcall-try-to-use-container-ipc-uts-net-pid-mnt.patch
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Tue Feb 23 12:15:39 UTC 2021 - Aurelien Aptel <aaptel@suse.com>
|
Tue Feb 23 12:15:39 UTC 2021 - Aurelien Aptel <aaptel@suse.com>
|
||||||
|
|
||||||
@ -53,6 +66,13 @@ Tue Nov 17 13:42:23 UTC 2020 - Ludwig Nussel <lnussel@suse.de>
|
|||||||
|
|
||||||
- prepare usrmerge (boo#1029961)
|
- prepare usrmerge (boo#1029961)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Aug 11 12:45:15 UTC 2020 - Aurelien Aptel <aaptel@suse.com>
|
||||||
|
|
||||||
|
- Make cifs-idmap plugin (idmapwb.so) use update-alternatives
|
||||||
|
mechanism to be able to switch between cifs-utils and sssd;
|
||||||
|
(bsc#1182682).
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Mon Aug 10 06:56:11 UTC 2020 - Aurelien Aptel <aaptel@suse.com>
|
Mon Aug 10 06:56:11 UTC 2020 - Aurelien Aptel <aaptel@suse.com>
|
||||||
|
|
||||||
|
@ -37,6 +37,20 @@ Source100: README.cifstab.migration
|
|||||||
Source1: cifs.init
|
Source1: cifs.init
|
||||||
|
|
||||||
Patch1: fix-sbin-install-error.patch
|
Patch1: fix-sbin-install-error.patch
|
||||||
|
Patch2: 0001-cifs.upcall-try-to-use-container-ipc-uts-net-pid-mnt.patch
|
||||||
|
Patch3: 0001-cifs.upcall-fix-regression-in-kerberos-mount.patch
|
||||||
|
|
||||||
|
# Both SSSD and cifs-utils provide an idmap plugin for cifs.ko
|
||||||
|
# /etc/cifs-utils/idmap-plugin should be a symlink to one of the 2 idmap plugins
|
||||||
|
# * cifs-utils one is the default (priority 20)
|
||||||
|
# * installing SSSD should NOT switch to SSSD plugin (priority 10)
|
||||||
|
%define cifs_idmap_plugin %{_sysconfdir}/cifs-utils/idmap-plugin
|
||||||
|
%define cifs_idmap_lib %{_libdir}/cifs-utils/idmapwb.so
|
||||||
|
%define cifs_idmap_name cifs-idmap-plugin
|
||||||
|
%define cifs_idmap_priority 20
|
||||||
|
BuildRequires: update-alternatives
|
||||||
|
Requires(post): update-alternatives
|
||||||
|
Requires(preun): update-alternatives
|
||||||
|
|
||||||
# cifs-utils 6.8 switched to python for man page generation
|
# cifs-utils 6.8 switched to python for man page generation
|
||||||
# we need to require either py2 or py3 package
|
# we need to require either py2 or py3 package
|
||||||
@ -121,6 +135,8 @@ for i in $pyscripts; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
%patch1 -p1
|
%patch1 -p1
|
||||||
|
%patch2 -p1
|
||||||
|
%patch3 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
export CFLAGS="%{optflags} -D_GNU_SOURCE -fpie"
|
export CFLAGS="%{optflags} -D_GNU_SOURCE -fpie"
|
||||||
@ -139,8 +155,6 @@ mkdir -p %{buildroot}/%{_sysconfdir}/init.d
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%make_install
|
%make_install
|
||||||
mkdir -p %{buildroot}%{_sysconfdir}/%{name}
|
|
||||||
ln -s %{_libdir}/%{name}/idmapwb.so %{buildroot}%{_sysconfdir}/%{name}/idmap-plugin
|
|
||||||
mkdir -p %{buildroot}%{_sysconfdir}/request-key.d
|
mkdir -p %{buildroot}%{_sysconfdir}/request-key.d
|
||||||
install -m 644 -p contrib/request-key.d/cifs.idmap.conf %{buildroot}%{_sysconfdir}/request-key.d
|
install -m 644 -p contrib/request-key.d/cifs.idmap.conf %{buildroot}%{_sysconfdir}/request-key.d
|
||||||
install -m 644 -p contrib/request-key.d/cifs.spnego.conf %{buildroot}%{_sysconfdir}/request-key.d
|
install -m 644 -p contrib/request-key.d/cifs.spnego.conf %{buildroot}%{_sysconfdir}/request-key.d
|
||||||
@ -156,6 +170,10 @@ install -m 0755 -p ${RPM_SOURCE_DIR}/cifs.init %{buildroot}/%{_sysconfdir}/init.
|
|||||||
ln -s service %{buildroot}/%{_sbindir}/rccifs
|
ln -s service %{buildroot}/%{_sbindir}/rccifs
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
# dummy target for cifs-idmap-plugin
|
||||||
|
mkdir -p %{buildroot}%{_sysconfdir}/alternatives %{buildroot}%{_sysconfdir}/cifs-utils
|
||||||
|
ln -s -f %{_sysconfdir}/alternatives/%{cifs_idmap_name} %{buildroot}%{cifs_idmap_plugin}
|
||||||
|
|
||||||
touch %{buildroot}/%{_sysconfdir}/sysconfig/network/if-{down,up}.d/${script} \
|
touch %{buildroot}/%{_sysconfdir}/sysconfig/network/if-{down,up}.d/${script} \
|
||||||
%{buildroot}%{_rundir}/cifs
|
%{buildroot}%{_rundir}/cifs
|
||||||
%endif
|
%endif
|
||||||
@ -164,6 +182,15 @@ touch %{buildroot}/%{_sysconfdir}/sysconfig/network/if-{down,up}.d/${script} \
|
|||||||
%fdupes %{buildroot}
|
%fdupes %{buildroot}
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%post
|
||||||
|
# install cifs-utils cifs-idmap plugin using alternatives system
|
||||||
|
update-alternatives --install %{cifs_idmap_plugin} %{cifs_idmap_name} %{cifs_idmap_lib} %{cifs_idmap_priority}
|
||||||
|
|
||||||
|
%postun
|
||||||
|
if [ ! -f %{cifs_idmap_lib} ] ; then
|
||||||
|
update-alternatives --remove %{cifs_idmap_name} %{cifs_idmap_lib}
|
||||||
|
fi
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%if 0%{?usrmerged}
|
%if 0%{?usrmerged}
|
||||||
%{_sbindir}/mount.cifs
|
%{_sbindir}/mount.cifs
|
||||||
@ -188,14 +215,20 @@ touch %{buildroot}/%{_sysconfdir}/sysconfig/network/if-{down,up}.d/${script} \
|
|||||||
%{_mandir}/man8/cifs.upcall.8%{ext_man}
|
%{_mandir}/man8/cifs.upcall.8%{ext_man}
|
||||||
%{_mandir}/man8/mount.cifs.8%{ext_man}
|
%{_mandir}/man8/mount.cifs.8%{ext_man}
|
||||||
%{_mandir}/man8/mount.smb3.8%{ext_man}
|
%{_mandir}/man8/mount.smb3.8%{ext_man}
|
||||||
|
|
||||||
|
# request keys
|
||||||
%dir %{_sysconfdir}/request-key.d
|
%dir %{_sysconfdir}/request-key.d
|
||||||
%config(noreplace) %{_sysconfdir}/request-key.d/cifs.idmap.conf
|
%config(noreplace) %{_sysconfdir}/request-key.d/cifs.idmap.conf
|
||||||
%config(noreplace) %{_sysconfdir}/request-key.d/cifs.spnego.conf
|
%config(noreplace) %{_sysconfdir}/request-key.d/cifs.spnego.conf
|
||||||
%dir %{_libdir}/cifs-utils
|
|
||||||
%dir %{_sysconfdir}/cifs-utils
|
# idmap plugin
|
||||||
%config(noreplace) %{_sysconfdir}/cifs-utils/idmap-plugin
|
%dir %_sysconfdir/cifs-utils
|
||||||
%{_libdir}/%{name}/idmapwb.so
|
%{cifs_idmap_plugin}
|
||||||
|
%dir %_libdir/cifs-utils
|
||||||
|
%{cifs_idmap_lib}
|
||||||
|
%ghost %_sysconfdir/alternatives/%{cifs_idmap_name}
|
||||||
%{_mandir}/man8/idmapwb.8%{ext_man}
|
%{_mandir}/man8/idmapwb.8%{ext_man}
|
||||||
|
|
||||||
%if 0%{?suse_version} > 1221
|
%if 0%{?suse_version} > 1221
|
||||||
%if ! %{systemd}
|
%if ! %{systemd}
|
||||||
%attr(0754,root,root) %config %{_sysconfdir}/init.d/cifs
|
%attr(0754,root,root) %config %{_sysconfdir}/init.d/cifs
|
||||||
|
Loading…
Reference in New Issue
Block a user