-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
* GPL HEADER START
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011 Whamcloud, Inc.
- *
+ * Copyright (c) 2011, 2014, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
* Lustre is a trademark of Sun Microsystems, Inc.
*/
+#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <libgen.h>
#include <syslog.h>
-#include <liblustre.h>
+#include <libcfs/util/param.h>
+#include <libcfs/util/string.h>
+#include <lnet/nidstr.h>
#include <lustre/lustre_user.h>
#include <lustre/lustre_idl.h>
* the valid values for perms are:
* setuid/setgid/setgrp/rmtacl -- enable corresponding perm
* nosetuid/nosetgid/nosetgrp/normtacl -- disable corresponding perm
- * they can be listed together, seperated by ',',
+ * they can be listed together, separated by ',',
* when perm and noperm are in the same line (item), noperm is preferential,
* when they are in different lines (items), the latter is preferential,
* '*' nid is as default perm, and is not preferential.
static void usage(void)
{
- fprintf(stderr,
- "\nusage: %s {mdtname} {uid}\n"
- "Normally invoked as an upcall from Lustre, set via:\n"
- "/proc/fs/lustre/mdt/${mdtname}/identity_upcall\n",
- progname);
+ fprintf(stderr,
+ "\nusage: %s {mdtname} {uid}\n"
+ "Normally invoked as an upcall from Lustre, set via:\n"
+ "lctl set_param mdt.${mdtname}.identity_upcall={path to upcall}\n",
+ progname);
}
static int compare_u32(const void *v1, const void *v2)
}
int get_groups_local(struct identity_downcall_data *data,
- unsigned int maxgroups)
+ unsigned int maxgroups)
{
- gid_t *groups;
- unsigned int ngroups = 0;
- struct passwd *pw;
- struct group *gr;
- char *pw_name;
- int namelen;
- int i;
-
- pw = getpwuid(data->idd_uid);
- if (!pw) {
- errlog("no such user %u\n", data->idd_uid);
- data->idd_err = errno ? errno : EIDRM;
- return -1;
- }
-
- data->idd_gid = pw->pw_gid;
- namelen = sysconf(_SC_LOGIN_NAME_MAX);
- if (namelen < _POSIX_LOGIN_NAME_MAX)
- namelen = _POSIX_LOGIN_NAME_MAX;
-
- pw_name = (char *)malloc(namelen);
- if (!pw_name) {
- errlog("malloc error\n");
- data->idd_err = errno;
- return -1;
- }
-
- memset(pw_name, 0, namelen);
- strncpy(pw_name, pw->pw_name, namelen - 1);
- groups = data->idd_groups;
-
- while ((gr = getgrent()) && ngroups < maxgroups) {
- if (gr->gr_gid == groups[0])
- continue;
- if (!gr->gr_mem)
- continue;
- for (i = 0; gr->gr_mem[i]; i++) {
- if (!strcmp(gr->gr_mem[i], pw_name)) {
- groups[ngroups++] = gr->gr_gid;
- break;
- }
- }
- }
- endgrent();
- if (ngroups > 0)
- qsort(groups, ngroups, sizeof(*groups), compare_u32);
- data->idd_ngroups = ngroups;
-
- free(pw_name);
- return 0;
+ gid_t *groups, *groups_tmp = NULL;
+ unsigned int ngroups = 0;
+ int ngroups_tmp;
+ struct passwd *pw;
+ char *pw_name;
+ int namelen;
+ int i;
+
+ pw = getpwuid(data->idd_uid);
+ if (!pw) {
+ errlog("no such user %u\n", data->idd_uid);
+ data->idd_err = errno ? errno : EIDRM;
+ return -1;
+ }
+
+ data->idd_gid = pw->pw_gid;
+ namelen = sysconf(_SC_LOGIN_NAME_MAX);
+ if (namelen < _POSIX_LOGIN_NAME_MAX)
+ namelen = _POSIX_LOGIN_NAME_MAX;
+
+ pw_name = malloc(namelen);
+ if (!pw_name) {
+ errlog("malloc error\n");
+ data->idd_err = errno;
+ return -1;
+ }
+
+ strlcpy(pw_name, pw->pw_name, namelen);
+ groups = data->idd_groups;
+
+ /* Allocate array of size maxgroups instead of handling two
+ * consecutive and potentially racy getgrouplist() calls. */
+ groups_tmp = malloc(maxgroups * sizeof(gid_t));
+ if (groups_tmp == NULL) {
+ free(pw_name);
+ data->idd_err = errno ? errno : ENOMEM;
+ errlog("malloc error=%u\n",data->idd_err);
+ return -1;
+ }
+
+ ngroups_tmp = maxgroups;
+ if (getgrouplist(pw->pw_name, pw->pw_gid, groups_tmp, &ngroups_tmp) <
+ 0) {
+ free(pw_name);
+ free(groups_tmp);
+ data->idd_err = errno ? errno : EIDRM;
+ errlog("getgrouplist() error for uid %u: error=%u\n",
+ data->idd_uid, data->idd_err);
+ return -1;
+ }
+
+ /* Do not place user's group ID in to the resulting groups list */
+ for (i = 0; i < ngroups_tmp; i++)
+ if (pw->pw_gid != groups_tmp[i])
+ groups[ngroups++] = groups_tmp[i];
+
+ if (ngroups > 0)
+ qsort(groups, ngroups, sizeof(*groups), compare_u32);
+ data->idd_ngroups = ngroups;
+
+ free(pw_name);
+ free(groups_tmp);
+ return 0;
}
static inline int comment_line(char *line)
*noperm = 0;
start = str;
while (1) {
- memset(name, 0, sizeof(name));
- end = strchr(start, ',');
- if (!end)
- end = str + strlen(str);
- if (start >= end)
- break;
- strncpy(name, start, end - start);
+ size_t len;
+ memset(name, 0, sizeof(name));
+ end = strchr(start, ',');
+ if (end == NULL)
+ end = str + strlen(str);
+ if (start >= end)
+ break;
+ len = end - start;
+ if (len >= sizeof(name))
+ return -E2BIG;
+ strncpy(name, start, len);
+ name[len] = '\0';
for (pt = perm_types; pt->name; pt++) {
if (!strcasecmp(name, pt->name)) {
*perm |= pt->bit;
return 0;
}
-int parse_perm_line(struct identity_downcall_data *data, char *line)
+static int
+parse_perm_line(struct identity_downcall_data *data, char *line, size_t size)
{
- char uid_str[256], nid_str[256], perm_str[256];
+ char uid_str[size];
+ char nid_str[size];
+ char perm_str[size];
lnet_nid_t nid;
__u32 perm, noperm;
int rc, i;
return -1;
}
- rc = sscanf(line, "%s %s %s", nid_str, uid_str, perm_str);
+ rc = sscanf(line, "%s %s %s", nid_str, uid_str, perm_str);
if (rc != 3) {
errlog("can't parse line %s\n", line);
return -1;
int get_perms(struct identity_downcall_data *data)
{
- FILE *fp;
- char line[1024];
+ FILE *fp;
+ char line[PATH_MAX];
fp = fopen(PERM_PATHNAME, "r");
if (fp == NULL) {
}
}
- while (fgets(line, 1024, fp)) {
+ while (fgets(line, sizeof(line), fp)) {
if (comment_line(line))
continue;
- if (parse_perm_line(data, line)) {
+ if (parse_perm_line(data, line, sizeof(line))) {
errlog("parse line %s failed!\n", line);
data->idd_err = EINVAL;
fclose(fp);
pdd = &data->idd_perms[i];
- printf(" "LPX64"\t0x%x\n", pdd->pdd_nid, pdd->pdd_perm);
+ printf(" %#jx\t0x%x\n", (uintmax_t)pdd->pdd_nid,
+ pdd->pdd_perm);
}
printf("\n");
}
int main(int argc, char **argv)
{
- char *end;
- struct identity_downcall_data *data = NULL;
- char procname[1024];
- unsigned long uid;
- int fd, rc = -EINVAL, size, maxgroups;
+ char *end;
+ struct identity_downcall_data *data = NULL;
+ glob_t path;
+ unsigned long uid;
+ int fd, rc = -EINVAL, size, maxgroups;
progname = basename(argv[0]);
if (argc != 3) {
maxgroups = sysconf(_SC_NGROUPS_MAX);
if (maxgroups > NGROUPS_MAX)
maxgroups = NGROUPS_MAX;
+ if (maxgroups == -1) {
+ rc = -EINVAL;
+ goto out;
+ }
size = offsetof(struct identity_downcall_data, idd_groups[maxgroups]);
data = malloc(size);
goto out;
}
- snprintf(procname, sizeof(procname),
- "/proc/fs/lustre/mdt/%s/identity_info", argv[1]);
- fd = open(procname, O_WRONLY);
- if (fd < 0) {
- errlog("can't open file %s: %s\n", procname, strerror(errno));
- rc = -1;
- goto out;
- }
-
- rc = write(fd, data, size);
- close(fd);
- if (rc != size) {
- errlog("partial write ret %d: %s\n", rc, strerror(errno));
- rc = -1;
- } else {
- rc = 0;
- }
-
+ rc = cfs_get_param_paths(&path, "mdt/%s/identity_info", argv[1]);
+ if (rc != 0) {
+ rc = -errno;
+ goto out;
+ }
+
+ fd = open(path.gl_pathv[0], O_WRONLY);
+ if (fd < 0) {
+ errlog("can't open file '%s':%s\n", path.gl_pathv[0],
+ strerror(errno));
+ rc = -errno;
+ goto out_params;
+ }
+
+ rc = write(fd, data, size);
+ close(fd);
+ if (rc != size) {
+ errlog("partial write ret %d: %s\n", rc, strerror(errno));
+ rc = -1;
+ } else {
+ rc = 0;
+ }
+
+out_params:
+ cfs_free_param_data(&path);
out:
- if (data != NULL)
- free(data);
- return rc;
+ if (data != NULL)
+ free(data);
+ return rc;
}