1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2005 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <sys/types.h>
35 #include <liblustre.h>
36 #include <linux/lustre_idl.h>
37 #include <linux/obd.h>
38 #include <linux/lustre_mds.h>
39 #include <linux/obd_support.h>
41 #include <portals/ptlctl.h>
42 #include <portals/types.h>
44 int switch_user_identity(uid_t uid)
48 int maxgroups, ngroups = 0;
53 /* originally must be root */
54 if (getuid() != 0 || geteuid() != 0)
57 /* nothing more is needed for root */
65 maxgroups = sysconf(_SC_NGROUPS_MAX);
66 groups = malloc(maxgroups * sizeof(gid_t));
76 while ((gr = getgrent())) {
79 for (i = 0; gr->gr_mem[i]; i++) {
80 if (strcmp(gr->gr_mem[i], pw->pw_name))
82 groups[ngroups++] = gr->gr_gid;
85 if (ngroups == maxgroups)
90 if (setgroups(ngroups, groups) == -1) {
96 if (setgid(gid) == -1) {
100 if (setuid(uid) == -1) {
108 * caller guarantee args not empty
110 int compose_command_line(char *cmdline, char *op, char *args)
112 char *p, *params, *file;
114 /* skip the white space at the tail */
115 p = args + strlen(args) - 1;
118 if (*p != ' ' && *p != '\t')
123 /* not allow empty args */
129 /* find next space */
131 if (*p == ' ' || *p == '\t')
138 file = p + 1; /* file name */
145 /* backward path not allowed */
146 if (strstr(file, ".."))
149 /* absolute path not allowed */
153 snprintf(cmdline, PATH_MAX, "%sfacl %s %s",
158 void do_acl_command(uid_t uid, char *lroot, char *cmdline)
160 if (switch_user_identity(uid)) {
161 printf("MDS: invalid user %u\n", uid);
165 if (chdir(lroot) < 0) {
166 printf("MDS: can't change dir\n");
170 execl("/bin/sh", "sh", "-c", cmdline, NULL);
171 printf("MDS: can't execute\n");
174 #define ERRSTR_NO_CMDLINE "No command line supplied\n"
175 #define ERRSTR_INVALID_ARGS "Invalid arguments\n"
176 #define ERRSTR_MDS_PROCESS "MDS procession error\n"
179 * The args passed in are:
186 #define OUTPUT_BUFSIZE 8192
187 int main (int argc, char **argv)
189 struct rmtacl_downcall_args dc_args;
190 char *dc_name = "/proc/fs/lustre/mds/lacl_downcall";
193 char output[OUTPUT_BUFSIZE];
194 char cmdline[PATH_MAX];
195 int pipeout[2], pipeerr[2], pid;
196 int output_size, rd, childret;
201 if (strcmp(argv[4], "get") && strcmp(argv[4], "set"))
204 dc_args.key = strtoull(argv[1], NULL, 16);
205 dc_args.res = output;
207 dc_args.status = -1; /* default return error */
211 if (strlen(argv[5]) == 0) {
212 dc_args.reslen = sizeof(ERRSTR_NO_CMDLINE);
213 memcpy(output, ERRSTR_NO_CMDLINE, dc_args.reslen);
217 if (compose_command_line(cmdline, argv[4], argv[5])) {
218 dc_args.reslen = sizeof(ERRSTR_INVALID_ARGS);
219 memcpy(output, ERRSTR_INVALID_ARGS, dc_args.reslen);
224 if (pipe(pipeout) < 0 || pipe(pipeerr) < 0) {
225 dc_args.reslen = sizeof(ERRSTR_MDS_PROCESS);
226 memcpy(output, ERRSTR_MDS_PROCESS, dc_args.reslen);
230 if ((pid = fork()) < 0) {
231 dc_args.reslen = sizeof(ERRSTR_MDS_PROCESS);
232 memcpy(output, ERRSTR_MDS_PROCESS, dc_args.reslen);
234 } else if (pid == 0) {
236 if (pipeout[1] != STDOUT_FILENO) {
237 dup2(pipeout[1], STDOUT_FILENO);
242 if (pipeerr[1] != STDERR_FILENO) {
243 dup2(pipeerr[1], STDERR_FILENO);
249 do_acl_command(uid, argv[3], cmdline);
253 /* parent process handling */
260 rd = read(pipeout[0], output + output_size,
261 OUTPUT_BUFSIZE - output_size);
263 output_size = sizeof(ERRSTR_MDS_PROCESS);
264 memcpy(output, ERRSTR_MDS_PROCESS, dc_args.reslen);
270 if (output_size >= OUTPUT_BUFSIZE)
274 /* if we got standard output, just leave; otherwise collect
277 if (output_size != 0)
281 rd = read(pipeerr[0], output + output_size,
282 OUTPUT_BUFSIZE - output_size);
284 output_size = sizeof(ERRSTR_MDS_PROCESS);
285 memcpy(output, ERRSTR_MDS_PROCESS, dc_args.reslen);
291 if (output_size >= OUTPUT_BUFSIZE)
298 dc_args.status = childret;
299 dc_args.reslen = output_size;
302 dc_fd = open(dc_name, O_WRONLY);
304 write(dc_fd, &dc_args, sizeof(dc_args));