Whamcloud - gitweb
LU-8955 nodemap: add SELinux policy info to nodemap
[fs/lustre-release.git] / lustre / ptlrpc / nodemap_lproc.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (C) 2013, Trustees of Indiana University
24  *
25  * Copyright (c) 2014, 2017, Intel Corporation.
26  *
27  * Author: Joshua Walgenbach <jjw@iu.edu>
28  */
29
30 #define NODEMAP_LPROC_ID_LEN 16
31 #define NODEMAP_LPROC_FLAG_LEN 2
32
33 #include <lprocfs_status.h>
34 #include <lustre_net.h>
35 #include <lustre_export.h>
36 #include <obd_class.h>
37 #include <interval_tree.h>
38 #include "nodemap_internal.h"
39
40 static LIST_HEAD(nodemap_pde_list);
41
42 /**
43  * Reads and prints the idmap for the given nodemap.
44  *
45  * \param       m               seq file in proc fs
46  * \param       data            unused
47  * \retval      0               success
48  */
49 static int nodemap_idmap_show(struct seq_file *m, void *data)
50 {
51         struct lu_nodemap       *nodemap;
52         struct lu_idmap         *idmap;
53         struct rb_node          *node;
54         bool                    cont = 0;
55         int rc;
56
57         mutex_lock(&active_config_lock);
58         nodemap = nodemap_lookup(m->private);
59         mutex_unlock(&active_config_lock);
60         if (IS_ERR(nodemap)) {
61                 rc = PTR_ERR(nodemap);
62                 CERROR("cannot find nodemap '%s': rc = %d\n",
63                         (char *)m->private, rc);
64                 return rc;
65         }
66
67         seq_printf(m, "[\n");
68         down_read(&nodemap->nm_idmap_lock);
69         for (node = rb_first(&nodemap->nm_client_to_fs_uidmap); node;
70                                 node = rb_next(node)) {
71                 if (cont)
72                         seq_printf(m, ",\n");
73                 cont = 1;
74                 idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
75                 if (idmap != NULL)
76                         seq_printf(m, " { idtype: uid, client_id: %u, "
77                                    "fs_id: %u }", idmap->id_client,
78                                    idmap->id_fs);
79         }
80         for (node = rb_first(&nodemap->nm_client_to_fs_gidmap);
81                                 node; node = rb_next(node)) {
82                 if (cont)
83                         seq_printf(m, ",\n");
84                 idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
85                 if (idmap != NULL)
86                         seq_printf(m, " { idtype: gid, client_id: %u, "
87                                    "fs_id: %u }", idmap->id_client,
88                                    idmap->id_fs);
89         }
90         up_read(&nodemap->nm_idmap_lock);
91         seq_printf(m, "\n");
92         seq_printf(m, "]\n");
93
94         nodemap_putref(nodemap);
95         return 0;
96 }
97
98 /**
99  * Attaches nodemap_idmap_show to proc file.
100  *
101  * \param       inode           inode of seq file in proc fs
102  * \param       file            seq file
103  * \retval      0               success
104  */
105 static int nodemap_idmap_open(struct inode *inode, struct file *file)
106 {
107         return single_open(file, nodemap_idmap_show, PDE_DATA(inode));
108 }
109
110 /**
111  * Reads and prints the NID ranges for the given nodemap.
112  *
113  * \param       m               seq file in proc fs
114  * \param       data            unused
115  * \retval      0               success
116  */
117 static int nodemap_ranges_show(struct seq_file *m, void *data)
118 {
119         struct lu_nodemap               *nodemap;
120         struct lu_nid_range             *range;
121         struct interval_node_extent     ext;
122         char                            start_nidstr[LNET_NIDSTR_SIZE];
123         char                            end_nidstr[LNET_NIDSTR_SIZE];
124         bool                            cont = false;
125         int rc;
126
127         mutex_lock(&active_config_lock);
128         nodemap = nodemap_lookup(m->private);
129         if (IS_ERR(nodemap)) {
130                 mutex_unlock(&active_config_lock);
131                 rc = PTR_ERR(nodemap);
132                 CERROR("cannot find nodemap '%s': rc = %d\n",
133                         (char *)m->private, rc);
134                 return rc;
135         }
136
137         seq_printf(m, "[\n");
138         down_read(&active_config->nmc_range_tree_lock);
139         list_for_each_entry(range, &nodemap->nm_ranges, rn_list) {
140                 if (cont)
141                         seq_printf(m, ",\n");
142                 cont = 1;
143                 ext = range->rn_node.in_extent;
144                 libcfs_nid2str_r(ext.start, start_nidstr, sizeof(start_nidstr));
145                 libcfs_nid2str_r(ext.end, end_nidstr, sizeof(end_nidstr));
146                 seq_printf(m, " { id: %u, start_nid: %s, end_nid: %s }",
147                            range->rn_id, start_nidstr, end_nidstr);
148         }
149         up_read(&active_config->nmc_range_tree_lock);
150         mutex_unlock(&active_config_lock);
151         seq_printf(m, "\n");
152         seq_printf(m, "]\n");
153
154         nodemap_putref(nodemap);
155         return 0;
156 }
157
158 /**
159  * Connects nodemap_idmap_show to proc file.
160  *
161  * \param       inode           inode of seq file in proc fs
162  * \param       file            seq file
163  * \retval      0               success
164  */
165 static int nodemap_ranges_open(struct inode *inode, struct file *file)
166 {
167         return single_open(file, nodemap_ranges_show, PDE_DATA(inode));
168 }
169
170 /**
171  * Reads and prints the fileset for the given nodemap.
172  *
173  * \param       m               seq file in proc fs
174  * \param       data            unused
175  * \retval      0               success
176  */
177 static int nodemap_fileset_seq_show(struct seq_file *m, void *data)
178 {
179         struct lu_nodemap *nodemap;
180         int rc = 0;
181
182         mutex_lock(&active_config_lock);
183         nodemap = nodemap_lookup(m->private);
184         mutex_unlock(&active_config_lock);
185         if (IS_ERR(nodemap)) {
186                 rc = PTR_ERR(nodemap);
187                 CERROR("cannot find nodemap '%s': rc = %d\n",
188                         (char *)m->private, rc);
189                 return rc;
190         }
191
192         seq_printf(m, "%s\n", nodemap->nm_fileset);
193         nodemap_putref(nodemap);
194         return rc;
195 }
196
197 /**
198  * Set a fileset on a nodemap.
199  *
200  * \param[in] file      proc file
201  * \param[in] buffer    string, "<fileset>"
202  * \param[in] count     \a buffer length
203  * \param[in] off       unused
204  * \retval              \a count on success
205  * \retval              negative number on error
206  */
207 static ssize_t
208 nodemap_fileset_seq_write(struct file *file,
209                                       const char __user *buffer,
210                                       size_t count, loff_t *off)
211 {
212         struct seq_file *m = file->private_data;
213         char *nm_fileset;
214         int rc = 0;
215         ENTRY;
216
217         if (count == 0)
218                 RETURN(0);
219
220         if (count > PATH_MAX)
221                 RETURN(-EINVAL);
222
223         OBD_ALLOC(nm_fileset, count + 1);
224         /* OBD_ALLOC zero-fills the buffer */
225         if (nm_fileset == NULL)
226                 RETURN(-ENOMEM);
227
228         if (copy_from_user(nm_fileset, buffer, count))
229                 GOTO(out, rc = -EFAULT);
230
231         rc = nodemap_set_fileset(m->private, nm_fileset);
232         if (rc != 0)
233                 GOTO(out, rc = -EINVAL);
234
235         rc = count;
236 out:
237         OBD_FREE(nm_fileset, count + 1);
238
239         return rc;
240 }
241 LPROC_SEQ_FOPS(nodemap_fileset);
242
243 /**
244  * Reads and prints the SELinux policy info for the given nodemap.
245  *
246  * \param       m               seq file in proc fs
247  * \param       data            unused
248  * \retval      0               success
249  */
250 static int nodemap_sepol_seq_show(struct seq_file *m, void *data)
251 {
252         struct lu_nodemap *nodemap;
253         int rc = 0;
254
255         mutex_lock(&active_config_lock);
256         nodemap = nodemap_lookup(m->private);
257         mutex_unlock(&active_config_lock);
258         if (IS_ERR(nodemap)) {
259                 rc = PTR_ERR(nodemap);
260                 CERROR("cannot find nodemap '%s': rc = %d\n",
261                         (char *)m->private, rc);
262                 return rc;
263         }
264
265         seq_printf(m, "%s\n", nodemap_get_sepol(nodemap));
266         nodemap_putref(nodemap);
267         return rc;
268 }
269
270 /**
271  * Set SELinux policy info on a nodemap.
272  *
273  * \param[in] file      proc file
274  * \param[in] buffer    string, "<sepol>"
275  * \param[in] count     \a buffer length
276  * \param[in] off       unused
277  * \retval              \a count on success
278  * \retval              negative number on error
279  */
280 static ssize_t
281 nodemap_sepol_seq_write(struct file *file,
282                         const char __user *buffer,
283                         size_t count, loff_t *off)
284 {
285         struct seq_file *m = file->private_data;
286         char sepol[LUSTRE_NODEMAP_SEPOL_LENGTH + 1];
287         int rc = 0;
288
289         CLASSERT(sizeof(sepol) == sizeof(((struct lu_nodemap *)0)->nm_sepol));
290
291         if (count > 0) {
292                 if (count >= sizeof(sepol))
293                         GOTO(out, rc = -ENAMETOOLONG);
294
295                 if (copy_from_user(sepol, buffer, count))
296                         GOTO(out, rc = -EFAULT);
297
298                 sepol[count] = '\0';
299
300                 rc = nodemap_set_sepol(m->private, sepol);
301         }
302
303 out:
304         if (rc != 0)
305                 return rc;
306
307         return count;
308 }
309 LPROC_SEQ_FOPS(nodemap_sepol);
310
311 /**
312  * Reads and prints the exports attached to the given nodemap.
313  *
314  * \param       m               seq file in proc fs, stores nodemap
315  * \param       data            unused
316  * \retval      0               success
317  */
318 static int nodemap_exports_show(struct seq_file *m, void *data)
319 {
320         struct lu_nodemap *nodemap;
321         struct obd_export *exp;
322         char nidstr[LNET_NIDSTR_SIZE] = "<unknown>";
323         int rc;
324
325         mutex_lock(&active_config_lock);
326         nodemap = nodemap_lookup(m->private);
327         mutex_unlock(&active_config_lock);
328         if (IS_ERR(nodemap)) {
329                 rc = PTR_ERR(nodemap);
330                 CERROR("cannot find nodemap '%s': rc = %d\n",
331                         (char *)m->private, rc);
332                 return rc;
333         }
334
335         seq_printf(m, "[\n");
336
337         mutex_lock(&nodemap->nm_member_list_lock);
338         list_for_each_entry(exp, &nodemap->nm_member_list,
339                             exp_target_data.ted_nodemap_member) {
340                 if (exp->exp_connection != NULL)
341                         libcfs_nid2str_r(exp->exp_connection->c_peer.nid,
342                                          nidstr, sizeof(nidstr));
343
344                 seq_printf(m, " { nid: %s, uuid: %s },",
345                            nidstr, exp->exp_client_uuid.uuid);
346         }
347         mutex_unlock(&nodemap->nm_member_list_lock);
348
349         seq_printf(m, "\n");
350         seq_printf(m, "]\n");
351
352         nodemap_putref(nodemap);
353         return 0;
354 }
355
356 /**
357  * Attaches nodemap_idmap_show to proc file.
358  *
359  * \param       inode           inode of seq file in proc fs
360  * \param       file            seq file
361  * \retval      0               success
362  */
363 static int nodemap_exports_open(struct inode *inode, struct file *file)
364 {
365         return single_open(file, nodemap_exports_show, PDE_DATA(inode));
366 }
367
368 /**
369  * Reads and prints the active flag for the given nodemap.
370  *
371  * \param       m               seq file in proc fs
372  * \param       data            unused
373  * \retval      0               success
374  */
375 static int nodemap_active_seq_show(struct seq_file *m, void *data)
376 {
377         seq_printf(m, "%u\n", (unsigned int)nodemap_active);
378         return 0;
379 }
380
381 /**
382  * Activate/deactivate nodemap.
383  *
384  * \param[in] file      proc file
385  * \param[in] buffer    string, "1" or "0" to activate/deactivate nodemap
386  * \param[in] count     \a buffer length
387  * \param[in] off       unused
388  * \retval              \a count on success
389  * \retval              negative number on error
390  */
391 static ssize_t
392 nodemap_active_seq_write(struct file *file, const char __user *buffer,
393                          size_t count, loff_t *off)
394 {
395         char                    active_string[NODEMAP_LPROC_FLAG_LEN + 1];
396         long unsigned int       active;
397         int                     rc;
398
399         if (count == 0)
400                 return 0;
401
402         if (count >= sizeof(active_string))
403                 return -EINVAL;
404
405         if (copy_from_user(active_string, buffer, count))
406                 return -EFAULT;
407
408         active_string[count] = '\0';
409         rc = kstrtoul(active_string, 10, &active);
410         if (rc != 0)
411                 return -EINVAL;
412
413         nodemap_activate(active);
414
415         return count;
416 }
417 LPROC_SEQ_FOPS(nodemap_active);
418
419 /**
420  * Reads and prints the nodemap ID for the given nodemap.
421  *
422  * \param       m               seq file in proc fs
423  * \param       data            unused
424  * \retval      0               success
425  */
426 static int nodemap_id_seq_show(struct seq_file *m, void *data)
427 {
428         struct lu_nodemap *nodemap;
429
430         mutex_lock(&active_config_lock);
431         nodemap = nodemap_lookup(m->private);
432         mutex_unlock(&active_config_lock);
433         if (IS_ERR(nodemap)) {
434                 int rc = PTR_ERR(nodemap);
435                 CERROR("cannot find nodemap '%s': rc = %d\n",
436                         (char *)m->private, rc);
437                 return rc;
438         }
439
440         seq_printf(m, "%u\n", nodemap->nm_id);
441         nodemap_putref(nodemap);
442         return 0;
443 }
444 LPROC_SEQ_FOPS_RO(nodemap_id);
445
446 /**
447  * Reads and prints the root squash UID for the given nodemap.
448  *
449  * \param       m               seq file in proc fs
450  * \param       data            unused
451  * \retval      0               success
452  */
453 static int nodemap_squash_uid_seq_show(struct seq_file *m, void *data)
454 {
455         struct lu_nodemap *nodemap;
456
457         mutex_lock(&active_config_lock);
458         nodemap = nodemap_lookup(m->private);
459         mutex_unlock(&active_config_lock);
460         if (IS_ERR(nodemap)) {
461                 int rc = PTR_ERR(nodemap);
462                 CERROR("cannot find nodemap '%s': rc = %d\n",
463                         (char *)m->private, rc);
464                 return rc;
465         }
466
467         seq_printf(m, "%u\n", nodemap->nm_squash_uid);
468         nodemap_putref(nodemap);
469         return 0;
470 }
471
472 /**
473  * Reads and prints the root squash GID for the given nodemap.
474  *
475  * \param       m               seq file in proc fs
476  * \param       data            unused
477  * \retval      0               success
478  */
479 static int nodemap_squash_gid_seq_show(struct seq_file *m, void *data)
480 {
481         struct lu_nodemap *nodemap;
482
483         mutex_lock(&active_config_lock);
484         nodemap = nodemap_lookup(m->private);
485         mutex_unlock(&active_config_lock);
486         if (IS_ERR(nodemap)) {
487                 int rc = PTR_ERR(nodemap);
488                 CERROR("cannot find nodemap '%s': rc = %d\n",
489                         (char *)m->private, rc);
490                 return rc;
491         }
492
493         seq_printf(m, "%u\n", nodemap->nm_squash_gid);
494         nodemap_putref(nodemap);
495         return 0;
496 }
497
498 /**
499  * Reads and prints the trusted flag for the given nodemap.
500  *
501  * \param       m               seq file in proc fs
502  * \param       data            unused
503  * \retval      0               success
504  */
505 static int nodemap_trusted_seq_show(struct seq_file *m, void *data)
506 {
507         struct lu_nodemap *nodemap;
508
509         mutex_lock(&active_config_lock);
510         nodemap = nodemap_lookup(m->private);
511         mutex_unlock(&active_config_lock);
512         if (IS_ERR(nodemap)) {
513                 int rc = PTR_ERR(nodemap);
514
515                 CERROR("cannot find nodemap '%s': rc = %d\n",
516                         (char *)m->private, rc);
517                 return rc;
518         }
519
520         seq_printf(m, "%d\n", (int)nodemap->nmf_trust_client_ids);
521         nodemap_putref(nodemap);
522         return 0;
523 }
524
525 /**
526  * Reads and prints the admin flag for the given nodemap.
527  *
528  * \param       m               seq file in proc fs
529  * \param       data            unused
530  * \retval      0               success
531  */
532 static int nodemap_admin_seq_show(struct seq_file *m, void *data)
533 {
534         struct lu_nodemap *nodemap;
535         int rc;
536
537         mutex_lock(&active_config_lock);
538         nodemap = nodemap_lookup(m->private);
539         mutex_unlock(&active_config_lock);
540         if (IS_ERR(nodemap)) {
541                 rc = PTR_ERR(nodemap);
542                 CERROR("cannot find nodemap '%s': rc = %d\n",
543                         (char *)m->private, rc);
544                 return rc;
545         }
546
547         seq_printf(m, "%d\n", (int)nodemap->nmf_allow_root_access);
548         nodemap_putref(nodemap);
549         return 0;
550 }
551
552 /**
553  * Reads and prints the mapping mode for the given nodemap.
554  *
555  * \param       m               seq file in proc fs
556  * \param       data            unused
557  * \retval      0               success
558  */
559 static int nodemap_map_mode_seq_show(struct seq_file *m, void *data)
560 {
561         struct lu_nodemap *nodemap;
562         int rc;
563
564         mutex_lock(&active_config_lock);
565         nodemap = nodemap_lookup(m->private);
566         mutex_unlock(&active_config_lock);
567         if (IS_ERR(nodemap)) {
568                 rc = PTR_ERR(nodemap);
569                 CERROR("cannot find nodemap '%s': rc = %d\n",
570                         (char *)m->private, rc);
571                 return rc;
572         }
573
574         if (nodemap->nmf_map_uid_only)
575                 seq_printf(m, "uid_only\n");
576         else if (nodemap->nmf_map_gid_only)
577                 seq_printf(m, "gid_only\n");
578         else
579                 seq_printf(m, "both\n");
580
581         nodemap_putref(nodemap);
582         return 0;
583 }
584
585 /**
586  * Reads and prints the deny_unknown flag for the given nodemap.
587  *
588  * \param       m               seq file in proc fs
589  * \param       data            unused
590  * \retval      0               success
591  */
592 static int nodemap_deny_unknown_seq_show(struct seq_file *m, void *data)
593 {
594         struct lu_nodemap *nodemap;
595         int rc;
596
597         mutex_lock(&active_config_lock);
598         nodemap = nodemap_lookup(m->private);
599         mutex_unlock(&active_config_lock);
600         if (IS_ERR(nodemap)) {
601                 rc = PTR_ERR(nodemap);
602                 CERROR("cannot find nodemap '%s': rc = %d\n",
603                         (char *)m->private, rc);
604                 return rc;
605         }
606
607         seq_printf(m, "%d\n", (int)nodemap->nmf_deny_unknown);
608         nodemap_putref(nodemap);
609         return 0;
610 }
611
612 /**
613  * Reads and prints the audit_mode flag for the given nodemap.
614  *
615  * \param       m               seq file in proc fs
616  * \param       data            unused
617  * \retval      0               success
618  */
619 static int nodemap_audit_mode_seq_show(struct seq_file *m, void *data)
620 {
621         struct lu_nodemap *nodemap;
622         int rc;
623
624         mutex_lock(&active_config_lock);
625         nodemap = nodemap_lookup(m->private);
626         mutex_unlock(&active_config_lock);
627         if (IS_ERR(nodemap)) {
628                 rc = PTR_ERR(nodemap);
629                 CERROR("cannot find nodemap '%s': rc = %d\n",
630                        (char *)m->private, rc);
631                 return rc;
632         }
633
634         seq_printf(m, "%d\n", (int)nodemap->nmf_enable_audit);
635         nodemap_putref(nodemap);
636         return 0;
637 }
638
639 #ifdef NODEMAP_PROC_DEBUG
640 /**
641  * Helper functions to set nodemap flags.
642  *
643  * \param[in] buffer    string, which is "1" or "0" to set/unset flag
644  * \param[in] count     \a buffer length
645  * \param[out] flag_p   where to store flag value
646  * \retval              \a count on success
647  * \retval              negative number on error
648  */
649 static int nodemap_proc_read_flag(const char __user *buffer,
650                                   unsigned long count, unsigned int *flag_p)
651 {
652         char                    scratch[NODEMAP_LPROC_FLAG_LEN + 1];
653         long unsigned int       flag_buf;
654         int                     rc;
655
656         if (count == 0)
657                 return 0;
658
659         if (count >= sizeof(scratch))
660                 return -EINVAL;
661
662         if (copy_from_user(scratch, buffer, count))
663                 return -EFAULT;
664
665         scratch[count] = '\0';
666         rc = kstrtoul(scratch, 10, &flag_buf);
667         if (rc != 0)
668                 return -EINVAL;
669
670         *flag_p = flag_buf;
671
672         return count;
673 }
674
675 /**
676  * Set the squash UID.
677  *
678  * \param[in] file      proc file
679  * \param[in] buffer    string representing squash UID to set
680  * \param[in] count     \a buffer length
681  * \param[in] off       unused
682  * \retval              \a count on success
683  * \retval              negative number on error
684  */
685 static ssize_t
686 nodemap_squash_uid_seq_write(struct file *file, const char __user *buffer,
687                              size_t count, loff_t *off)
688 {
689         char                     squash[NODEMAP_LPROC_ID_LEN + 1];
690         struct seq_file         *m = file->private_data;
691         long unsigned int        squash_uid;
692         int                      rc;
693
694         if (count == 0)
695                 return 0;
696
697         if (count >= sizeof(squash))
698                 return -EINVAL;
699
700         if (copy_from_user(squash, buffer, count))
701                 return -EFAULT;
702
703         squash[count] = '\0';
704         rc = kstrtoul(squash, 10, &squash_uid);
705         if (rc != 0)
706                 return -EINVAL;
707
708         rc = nodemap_set_squash_uid(m->private, squash_uid);
709         if (rc != 0)
710                 return rc;
711
712         return count;
713 }
714
715 /**
716  * Set the squash GID.
717  *
718  * \param[in] file      proc file
719  * \param[in] buffer    string representing squash GID to set
720  * \param[in] count     \a buffer length
721  * \param[in] off       unused
722  * \retval              \a count on success
723  * \retval              negative number on error
724  */
725 static ssize_t
726 nodemap_squash_gid_seq_write(struct file *file, const char __user *buffer,
727                              size_t count, loff_t *off)
728 {
729         char                     squash[NODEMAP_LPROC_ID_LEN + 1];
730         struct seq_file         *m = file->private_data;
731         long unsigned int        squash_gid;
732         int                      rc;
733
734         if (count == 0)
735                 return 0;
736
737         if (count >= sizeof(squash))
738                 return -EINVAL;
739
740         if (copy_from_user(squash, buffer, count))
741                 return -EFAULT;
742
743         squash[count] = '\0';
744         rc = kstrtoul(squash, 10, &squash_gid);
745         if (rc != 0)
746                 return -EINVAL;
747
748         rc = nodemap_set_squash_gid(m->private, squash_gid);
749         if (rc != 0)
750                 return rc;
751
752         return count;
753 }
754
755 /**
756  * Set/unset the trusted flag.
757  *
758  * \param[in] file      proc file
759  * \param[in] buffer    string, "1" or "0"
760  * \param[in] count     \a buffer length
761  * \param[in] off       unused
762  * \retval              \a count on success
763  * \retval              negative number on error
764  */
765 static ssize_t
766 nodemap_trusted_seq_write(struct file *file, const char __user *buffer,
767                           size_t count, loff_t *off)
768 {
769         struct seq_file         *m = file->private_data;
770         int                     flags;
771         int                     rc;
772
773         rc = nodemap_proc_read_flag(buffer, count, &flags);
774         if (rc < 0)
775                 return rc;
776
777         rc = nodemap_set_trust_client_ids(m->private, flags);
778         if (rc != 0)
779                 return rc;
780
781         return count;
782 }
783
784 /**
785  * Set/unset the admin flag.
786  *
787  * \param[in] file      proc file
788  * \param[in] buffer    string, "1" or "0"
789  * \param[in] count     \a buffer length
790  * \param[in] off       unused
791  * \retval              \a count on success
792  * \retval              negative number on error
793  */
794 static ssize_t
795 nodemap_admin_seq_write(struct file *file, const char __user *buffer,
796                         size_t count, loff_t *off)
797 {
798         struct seq_file         *m = file->private_data;
799         int                     flags;
800         int                     rc;
801
802         rc = nodemap_proc_read_flag(buffer, count, &flags);
803         if (rc < 0)
804                 return rc;
805
806         rc = nodemap_set_allow_root(m->private, flags);
807         if (rc != 0)
808                 return rc;
809
810         return count;
811 }
812
813 /**
814  * Add a nodemap.
815  *
816  * \param[in] file      proc file
817  * \param[in] buffer    string, name of the nodemap to add
818  * \param[in] count     \a buffer length
819  * \param[in] off       unused
820  * \retval              \a count on success
821  * \retval              negative number on error
822  */
823 static ssize_t
824 lprocfs_add_nodemap_seq_write(struct file *file, const char __user *buffer,
825                               size_t count, loff_t *off)
826 {
827         char    nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
828         char    *cpybuf = NULL;
829         char    *pos;
830         int     rc;
831
832         if (count == 0)
833                 return 0;
834
835         if (count >= sizeof(nodemap_name))
836                 return -EINVAL;
837
838         if (copy_from_user(nodemap_name, buffer, count))
839                 return -EFAULT;
840
841         nodemap_name[count] = '\0';
842
843         cpybuf = nodemap_name;
844         pos = strsep(&cpybuf, " \n");
845         if (pos == NULL)
846                 return -EINVAL;
847
848         rc = nodemap_add(nodemap_name);
849         if (rc == 0)
850                 rc = count;
851
852         return rc;
853 }
854 LPROC_SEQ_FOPS_WR_ONLY(nodemap, add_nodemap);
855
856 /**
857  * Delete a nodemap.
858  *
859  * \param[in] file      proc file
860  * \param[in] buffer    string, name of the nodemap to delete
861  * \param[in] count     \a buffer length
862  * \param[in] off       unused
863  * \retval              \a count on success
864  * \retval              negative number on error
865  */
866 static ssize_t
867 lprocfs_del_nodemap_seq_write(struct file *file, const char __user *buffer,
868                               size_t count, loff_t *off)
869 {
870         char    nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
871         char    *cpybuf = NULL;
872         char    *pos;
873         int     rc = count;
874
875         if (count == 0)
876                 return 0;
877
878         if (count >= sizeof(nodemap_name))
879                 return -EINVAL;
880
881         if (copy_from_user(nodemap_name, buffer, count))
882                 return -EFAULT;
883
884         nodemap_name[count] = '\0';
885
886         cpybuf = nodemap_name;
887         pos = strsep(&cpybuf, " \n");
888         if (pos == NULL)
889                 return -EINVAL;
890
891         rc = nodemap_del(nodemap_name);
892         if (rc == 0)
893                 rc = count;
894
895         return rc;
896
897 }
898 LPROC_SEQ_FOPS_WR_ONLY(nodemap, del_nodemap);
899
900 /**
901  * Helper function to parse a NID string.
902  *
903  * \param[in] rangestr  string representation of NIDs, see libcfs_str2nid()
904  * \param[out] nids     array of two nids
905  * \retval              0 on success
906  * \retval              negative number on error
907  */
908 static int parse_nids(char *rangestr, lnet_nid_t nids[2])
909 {
910         struct list_head        nidlist;
911         char                    nidstr[2][LNET_NIDSTR_SIZE];
912         char                    nidrange_str[2 * LNET_NIDSTR_SIZE + 2];
913         int                     rc = 0;
914
915         INIT_LIST_HEAD(&nidlist);
916
917         if (cfs_parse_nidlist(rangestr, strlen(rangestr),
918             &nidlist) <= 0)
919                 return -EINVAL;
920
921         rc = cfs_nidrange_find_min_max(&nidlist, nidstr[0], nidstr[1],
922                                        LNET_NIDSTR_SIZE);
923         if (rc < 0)
924                 return rc;
925
926         snprintf(nidrange_str, sizeof(nidrange_str), "%s:%s",
927                 nidstr[0], nidstr[1]);
928
929         rc = nodemap_parse_range(nidrange_str, nids);
930         if (rc != 0)
931                 return -EINVAL;
932
933         cfs_free_nidlist(&nidlist);
934
935         return 0;
936 }
937
938 /**
939  * Add a NID range to nodemap.
940  *
941  * \param[in] file      proc file
942  * \param[in] buffer    string, "<nodemap name> <nid range>"
943  * \param[in] count     \a buffer length
944  * \param[in] off       unused
945  * \retval              \a count on success
946  * \retval              negative number on error
947  */
948 static ssize_t
949 lprocfs_add_nodemap_range_seq_write(struct file *file,
950                                     const char __user *buffer,
951                                     size_t count, loff_t *off)
952 {
953         char                    name_range[LUSTRE_NODEMAP_NAME_LENGTH +
954                                            LNET_NIDSTR_SIZE * 2 + 2];
955         char                    *cpybuf = NULL;
956         char                    *name;
957         char                    *rangestr = NULL;
958         lnet_nid_t              nids[2];
959         int                     rc;
960
961         if (count == 0)
962                 return 0;
963
964         if (count >= sizeof(name_range))
965                 GOTO(out, rc = -EINVAL);
966
967         if (copy_from_user(name_range, buffer, count))
968                 GOTO(out, rc = -EFAULT);
969
970         name_range[count] = '\0';
971
972         cpybuf = name_range;
973         name = strsep(&cpybuf, " ");
974         if (name == NULL)
975                 GOTO(out, rc = -EINVAL);
976
977         rangestr = strsep(&cpybuf, " \n");
978         if (rangestr == NULL)
979                 GOTO(out, rc = -EINVAL);
980
981         rc = parse_nids(rangestr, nids);
982         if (rc != 0)
983                 GOTO(out, rc = rc);
984
985         rc = nodemap_add_range(name, nids);
986         if (rc != 0)
987                 GOTO(out, rc = -EINVAL);
988
989         if (rc == 0)
990                 rc = count;
991
992 out:
993         return rc;
994 }
995 LPROC_SEQ_FOPS_WR_ONLY(nodemap, add_nodemap_range);
996
997 /**
998  * Delete a NID range from nodemap.
999  *
1000  * \param[in] file      proc file
1001  * \param[in] buffer    string, "<nodemap name> <nid range>"
1002  * \param[in] count     \a buffer length
1003  * \param[in] off       unused
1004  * \retval              \a count on success
1005  * \retval              negative number on error
1006  */
1007 static ssize_t
1008 lprocfs_del_nodemap_range_seq_write(struct file *file,
1009                                     const char __user *buffer,
1010                                     size_t count, loff_t *off)
1011 {
1012         char                    name_range[LUSTRE_NODEMAP_NAME_LENGTH +
1013                                            LNET_NIDSTR_SIZE * 2 + 2];
1014         char                    *cpybuf = NULL;
1015         char                    *name;
1016         char                    *rangestr = NULL;
1017         lnet_nid_t              nids[2];
1018         int                     rc;
1019
1020         if (count == 0)
1021                 return 0;
1022
1023         if (count >= sizeof(name_range))
1024                 GOTO(out, rc = -EINVAL);
1025
1026         if (copy_from_user(name_range, buffer, count))
1027                 GOTO(out, rc = -EFAULT);
1028
1029         name_range[count] = '\0';
1030
1031         cpybuf = name_range;
1032         name = strsep(&cpybuf, " ");
1033         if (name == NULL)
1034                 GOTO(out, rc = -EINVAL);
1035
1036         rangestr = strsep(&cpybuf, " \n");
1037         if (rangestr == NULL)
1038                 GOTO(out, rc = -EINVAL);
1039
1040         rc = parse_nids(rangestr, nids);
1041         if (rc != 0)
1042                 GOTO(out, rc = rc);
1043
1044         rc = nodemap_del_range(name, nids);
1045         if (rc != 0)
1046                 GOTO(out, rc = -EINVAL);
1047
1048         if (rc == 0)
1049                 rc = count;
1050
1051 out:
1052         return rc;
1053 }
1054 LPROC_SEQ_FOPS_WR_ONLY(nodemap, del_nodemap_range);
1055
1056 /**
1057  * Add an idmap to nodemap.
1058  *
1059  * \param[in] file      proc file
1060  * \param[in] buffer    string, "<nodemap name> <uid|gid> <idmap>"
1061  * \param[in] count     \a buffer length
1062  * \param[in] off       unused
1063  * \retval              \a count on success
1064  * \retval              negative number on error
1065  */
1066 static ssize_t
1067 lprocfs_add_nodemap_idmap_seq_write(struct file *file,
1068                                     const char __user *buffer,
1069                                     size_t count, loff_t *off)
1070 {
1071         char                    name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
1072         char                    *cpybuf = NULL;
1073         char                    *name;
1074         char                    *idtypestr = NULL;
1075         char                    *idmapstr = NULL;
1076         __u32                   idmap[2];
1077         int                     rc = count;
1078
1079         if (count == 0)
1080                 return 0;
1081
1082         if (count >= sizeof(name_idmapstr))
1083                 GOTO(out, rc = -EINVAL);
1084
1085         if (copy_from_user(name_idmapstr, buffer, count))
1086                 GOTO(out, rc = -EFAULT);
1087
1088         name_idmapstr[count] = '\0';
1089
1090         cpybuf = name_idmapstr;
1091         name = strsep(&cpybuf, " ");
1092         if (name == NULL)
1093                 GOTO(out, rc = -EINVAL);
1094
1095         idtypestr = strsep(&cpybuf, " ");
1096         if (idtypestr == NULL)
1097                 GOTO(out, rc = -EINVAL);
1098
1099         idmapstr = strsep(&cpybuf, " \n");
1100         if (idmapstr == NULL)
1101                 GOTO(out, rc = -EINVAL);
1102
1103         rc = nodemap_parse_idmap(idmapstr, idmap);
1104         if (rc != 0)
1105                 GOTO(out, rc = -EINVAL);
1106
1107         if (strcmp(idtypestr, "uid") == 0)
1108                 rc = nodemap_add_idmap(name, NODEMAP_UID, idmap);
1109         else if (strcmp(idtypestr, "gid") == 0)
1110                 rc = nodemap_add_idmap(name, NODEMAP_GID, idmap);
1111         else
1112                 GOTO(out, rc = -EINVAL);
1113
1114         if (rc != 0)
1115                 GOTO(out, rc = -EINVAL);
1116
1117         if (rc == 0)
1118                 rc = count;
1119
1120 out:
1121         return rc;
1122 }
1123 LPROC_SEQ_FOPS_WR_ONLY(nodemap, add_nodemap_idmap);
1124
1125 /**
1126  * Delete an idmap from nodemap.
1127  *
1128  * \param[in] file      proc file
1129  * \param[in] buffer    string, "<nodemap name> <uid|gid> <idmap>"
1130  * \param[in] count     \a buffer length
1131  * \param[in] off       unused
1132  * \retval              \a count on success
1133  * \retval              negative number on error
1134  */
1135 static ssize_t
1136 lprocfs_del_nodemap_idmap_seq_write(struct file *file,
1137                                     const char __user *buffer,
1138                                     size_t count, loff_t *off)
1139 {
1140         char                    name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
1141         char                    *cpybuf = NULL;
1142         char                    *name;
1143         char                    *idtypestr = NULL;
1144         char                    *idmapstr = NULL;
1145         __u32                   idmap[2];
1146         int                     rc = count;
1147
1148         if (count == 0)
1149                 return 0;
1150
1151         if (count >= sizeof(name_idmapstr))
1152                 GOTO(out, rc = -EINVAL);
1153
1154         if (copy_from_user(name_idmapstr, buffer, count))
1155                 GOTO(out, rc = -EFAULT);
1156
1157         name_idmapstr[count] = '\0';
1158
1159         cpybuf = name_idmapstr;
1160         name = strsep(&cpybuf, " ");
1161         if (name == NULL)
1162                 GOTO(out, rc = -EINVAL);
1163
1164         idtypestr = strsep(&cpybuf, " ");
1165         if (idtypestr == NULL)
1166                 GOTO(out, rc = -EINVAL);
1167
1168         idmapstr = strsep(&cpybuf, " \n");
1169         if (idmapstr == NULL)
1170                 GOTO(out, rc = -EINVAL);
1171
1172         rc = nodemap_parse_idmap(idmapstr, idmap);
1173         if (rc != 0)
1174                 GOTO(out, rc = -EINVAL);
1175
1176         if (strcmp(idtypestr, "uid") == 0)
1177                 rc = nodemap_del_idmap(name, NODEMAP_UID, idmap);
1178         else if (strcmp(idtypestr, "gid") == 0)
1179                 rc = nodemap_del_idmap(name, NODEMAP_GID, idmap);
1180         else
1181                 GOTO(out, rc = -EINVAL);
1182
1183         if (rc != 0)
1184                 GOTO(out, rc = -EINVAL);
1185
1186         if (rc == 0)
1187                 rc = count;
1188
1189 out:
1190         return rc;
1191 }
1192 LPROC_SEQ_FOPS_WR_ONLY(nodemap, del_nodemap_idmap);
1193 #endif /* NODEMAP_PROC_DEBUG */
1194
1195 static struct lprocfs_vars lprocfs_nm_module_vars[] = {
1196         {
1197                 .name           = "active",
1198                 .fops           = &nodemap_active_fops,
1199         },
1200 #ifdef NODEMAP_PROC_DEBUG
1201         {
1202                 .name           = "add_nodemap",
1203                 .fops           = &nodemap_add_nodemap_fops,
1204         },
1205         {
1206                 .name           = "remove_nodemap",
1207                 .fops           = &nodemap_del_nodemap_fops,
1208         },
1209         {
1210                 .name           = "add_nodemap_range",
1211                 .fops           = &nodemap_add_nodemap_range_fops,
1212         },
1213         {
1214                 .name           = "del_nodemap_range",
1215                 .fops           = &nodemap_del_nodemap_range_fops,
1216         },
1217         {
1218                 .name           = "add_nodemap_idmap",
1219                 .fops           = &nodemap_add_nodemap_idmap_fops,
1220         },
1221         {
1222                 .name           = "del_nodemap_idmap",
1223                 .fops           = &nodemap_del_nodemap_idmap_fops,
1224         },
1225 #endif /* NODEMAP_PROC_DEBUG */
1226         {
1227                 NULL
1228         }
1229 };
1230
1231 #ifdef NODEMAP_PROC_DEBUG
1232 LPROC_SEQ_FOPS(nodemap_trusted);
1233 LPROC_SEQ_FOPS(nodemap_admin);
1234 LPROC_SEQ_FOPS(nodemap_squash_uid);
1235 LPROC_SEQ_FOPS(nodemap_squash_gid);
1236 #else
1237 LPROC_SEQ_FOPS_RO(nodemap_trusted);
1238 LPROC_SEQ_FOPS_RO(nodemap_admin);
1239 LPROC_SEQ_FOPS_RO(nodemap_squash_uid);
1240 LPROC_SEQ_FOPS_RO(nodemap_squash_gid);
1241 #endif
1242
1243 LPROC_SEQ_FOPS_RO(nodemap_deny_unknown);
1244 LPROC_SEQ_FOPS_RO(nodemap_map_mode);
1245 LPROC_SEQ_FOPS_RO(nodemap_audit_mode);
1246
1247 const struct file_operations nodemap_ranges_fops = {
1248         .open                   = nodemap_ranges_open,
1249         .read                   = seq_read,
1250         .llseek                 = seq_lseek,
1251         .release                = single_release
1252 };
1253
1254 const struct file_operations nodemap_idmap_fops = {
1255         .open                   = nodemap_idmap_open,
1256         .read                   = seq_read,
1257         .llseek                 = seq_lseek,
1258         .release                = single_release
1259 };
1260
1261 const struct file_operations nodemap_exports_fops = {
1262         .open                   = nodemap_exports_open,
1263         .read                   = seq_read,
1264         .llseek                 = seq_lseek,
1265         .release                = single_release
1266 };
1267
1268 static struct lprocfs_vars lprocfs_nodemap_vars[] = {
1269         {
1270                 .name           = "id",
1271                 .fops           = &nodemap_id_fops,
1272         },
1273         {
1274                 .name           = "trusted_nodemap",
1275                 .fops           = &nodemap_trusted_fops,
1276         },
1277         {
1278                 .name           = "admin_nodemap",
1279                 .fops           = &nodemap_admin_fops,
1280         },
1281         {
1282                 .name           = "deny_unknown",
1283                 .fops           = &nodemap_deny_unknown_fops,
1284         },
1285         {
1286                 .name           = "map_mode",
1287                 .fops           = &nodemap_map_mode_fops,
1288         },
1289         {
1290                 .name           = "audit_mode",
1291                 .fops           = &nodemap_audit_mode_fops,
1292         },
1293         {
1294                 .name           = "squash_uid",
1295                 .fops           = &nodemap_squash_uid_fops,
1296         },
1297         {
1298                 .name           = "squash_gid",
1299                 .fops           = &nodemap_squash_gid_fops,
1300         },
1301         {
1302                 .name           = "ranges",
1303                 .fops           = &nodemap_ranges_fops,
1304         },
1305         {
1306                 .name           = "fileset",
1307                 .fops           = &nodemap_fileset_fops,
1308         },
1309         {
1310                 .name           = "sepol",
1311                 .fops           = &nodemap_sepol_fops,
1312         },
1313         {
1314                 .name           = "exports",
1315                 .fops           = &nodemap_exports_fops,
1316         },
1317         {
1318                 .name           = "idmap",
1319                 .fops           = &nodemap_idmap_fops,
1320         },
1321         {
1322                 NULL
1323         }
1324 };
1325
1326 static struct lprocfs_vars lprocfs_default_nodemap_vars[] = {
1327         {
1328                 .name           = "id",
1329                 .fops           = &nodemap_id_fops,
1330         },
1331         {
1332                 .name           = "trusted_nodemap",
1333                 .fops           = &nodemap_trusted_fops,
1334         },
1335         {
1336                 .name           = "admin_nodemap",
1337                 .fops           = &nodemap_admin_fops,
1338         },
1339         {
1340                 .name           = "squash_uid",
1341                 .fops           = &nodemap_squash_uid_fops,
1342         },
1343         {
1344                 .name           = "squash_gid",
1345                 .fops           = &nodemap_squash_gid_fops,
1346         },
1347         {
1348                 .name           = "fileset",
1349                 .fops           = &nodemap_fileset_fops,
1350         },
1351         {
1352                 .name           = "exports",
1353                 .fops           = &nodemap_exports_fops,
1354         },
1355         {
1356                 .name           = "audit_mode",
1357                 .fops           = &nodemap_audit_mode_fops,
1358         },
1359         {
1360                 NULL
1361         }
1362 };
1363
1364 /**
1365  * Initialize the nodemap procfs directory.
1366  *
1367  * \retval      0               success
1368  */
1369 int nodemap_procfs_init(void)
1370 {
1371         int rc = 0;
1372
1373         proc_lustre_nodemap_root = lprocfs_register(LUSTRE_NODEMAP_NAME,
1374                                                     proc_lustre_root,
1375                                                     lprocfs_nm_module_vars,
1376                                                     NULL);
1377         if (IS_ERR(proc_lustre_nodemap_root)) {
1378                 rc = PTR_ERR(proc_lustre_nodemap_root);
1379                 CERROR("cannot create 'nodemap' directory: rc = %d\n",
1380                        rc);
1381                 proc_lustre_nodemap_root = NULL;
1382         }
1383         return rc;
1384 }
1385
1386 /**
1387  * Cleanup nodemap proc entry data structures.
1388  */
1389 void nodemap_procfs_exit(void)
1390 {
1391         struct nodemap_pde *nm_pde;
1392         struct nodemap_pde *tmp;
1393
1394         lprocfs_remove(&proc_lustre_nodemap_root);
1395         list_for_each_entry_safe(nm_pde, tmp, &nodemap_pde_list,
1396                                  npe_list_member) {
1397                 list_del(&nm_pde->npe_list_member);
1398                 OBD_FREE_PTR(nm_pde);
1399         }
1400 }
1401
1402 /**
1403  * Remove a nodemap's procfs entry and related data.
1404  */
1405 void lprocfs_nodemap_remove(struct nodemap_pde *nm_pde)
1406 {
1407         lprocfs_remove(&nm_pde->npe_proc_entry);
1408         list_del(&nm_pde->npe_list_member);
1409         OBD_FREE_PTR(nm_pde);
1410 }
1411
1412 /**
1413  * Register the proc directory for a nodemap
1414  *
1415  * \param       nodemap         nodemap to make the proc dir for
1416  * \param       is_default:     1 if default nodemap
1417  * \retval      0               success
1418  */
1419 int lprocfs_nodemap_register(struct lu_nodemap *nodemap, bool is_default)
1420 {
1421         struct nodemap_pde      *nm_entry;
1422         int                      rc = 0;
1423
1424         OBD_ALLOC_PTR(nm_entry);
1425         if (nm_entry == NULL)
1426                 GOTO(out, rc = -ENOMEM);
1427
1428         nm_entry->npe_proc_entry = proc_mkdir(nodemap->nm_name,
1429                                               proc_lustre_nodemap_root);
1430         if (IS_ERR(nm_entry->npe_proc_entry))
1431                 GOTO(out, rc = PTR_ERR(nm_entry->npe_proc_entry));
1432
1433         snprintf(nm_entry->npe_name, sizeof(nm_entry->npe_name), "%s",
1434                  nodemap->nm_name);
1435
1436         /* Use the nodemap name as stored on the PDE as the private data. This
1437          * is so a nodemap struct can be replaced without updating the proc
1438          * entries.
1439          */
1440         rc = lprocfs_add_vars(nm_entry->npe_proc_entry,
1441                               (is_default ? lprocfs_default_nodemap_vars :
1442                                             lprocfs_nodemap_vars),
1443                               nm_entry->npe_name);
1444         if (rc != 0)
1445                 lprocfs_remove(&nm_entry->npe_proc_entry);
1446         else
1447                 list_add(&nm_entry->npe_list_member, &nodemap_pde_list);
1448
1449 out:
1450         if (rc != 0) {
1451                 CERROR("cannot create 'nodemap/%s': rc = %d\n",
1452                        nodemap->nm_name, rc);
1453                 if (nm_entry != NULL) {
1454                         OBD_FREE_PTR(nm_entry);
1455                         nm_entry = NULL;
1456                 }
1457         }
1458
1459         nodemap->nm_pde_data = nm_entry;
1460
1461         return rc;
1462 }