1*f37b3cbbSMatt Barden /*
2*f37b3cbbSMatt Barden * This file and its contents are supplied under the terms of the
3*f37b3cbbSMatt Barden * Common Development and Distribution License ("CDDL"), version 1.0.
4*f37b3cbbSMatt Barden * You may only use this file in accordance with the terms of version
5*f37b3cbbSMatt Barden * 1.0 of the CDDL.
6*f37b3cbbSMatt Barden *
7*f37b3cbbSMatt Barden * A full copy of the text of the CDDL should have accompanied this
8*f37b3cbbSMatt Barden * source. A copy of the CDDL is also available via the Internet at
9*f37b3cbbSMatt Barden * http://www.illumos.org/license/CDDL.
10*f37b3cbbSMatt Barden */
11*f37b3cbbSMatt Barden
12*f37b3cbbSMatt Barden /*
13*f37b3cbbSMatt Barden * Copyright 2020 Tintri by DDN, Inc. All rights reserved.
14*f37b3cbbSMatt Barden */
15*f37b3cbbSMatt Barden
16*f37b3cbbSMatt Barden /*
17*f37b3cbbSMatt Barden * Test the kernel ksid interfaces used by ZFS and SMB
18*f37b3cbbSMatt Barden */
19*f37b3cbbSMatt Barden
20*f37b3cbbSMatt Barden #include <sys/sid.h>
21*f37b3cbbSMatt Barden #include <sys/time.h>
22*f37b3cbbSMatt Barden #include <stdio.h>
23*f37b3cbbSMatt Barden #include <stdlib.h>
24*f37b3cbbSMatt Barden #include <strings.h>
25*f37b3cbbSMatt Barden #include <errno.h>
26*f37b3cbbSMatt Barden
27*f37b3cbbSMatt Barden extern int ksl_bin_search_cutoff;
28*f37b3cbbSMatt Barden
29*f37b3cbbSMatt Barden #define MAX_DOMAINS 8
30*f37b3cbbSMatt Barden #define DEFAULT_NUMSIDS 128
31*f37b3cbbSMatt Barden #define DEFAULT_ITERS 1
32*f37b3cbbSMatt Barden
33*f37b3cbbSMatt Barden char ksid_sids[MAX_DOMAINS+2][256];
34*f37b3cbbSMatt Barden ksid_t *bad_ksids;
35*f37b3cbbSMatt Barden
36*f37b3cbbSMatt Barden boolean_t
run_test(ksidlist_t * ksl,uint32_t idx,uint32_t numsids,uint32_t iters,boolean_t pid)37*f37b3cbbSMatt Barden run_test(ksidlist_t *ksl, uint32_t idx, uint32_t numsids,
38*f37b3cbbSMatt Barden uint32_t iters, boolean_t pid)
39*f37b3cbbSMatt Barden {
40*f37b3cbbSMatt Barden uint64_t savenum = ksl->ksl_nsid;
41*f37b3cbbSMatt Barden uint64_t success = 0;
42*f37b3cbbSMatt Barden hrtime_t start, end;
43*f37b3cbbSMatt Barden uint32_t i, id;
44*f37b3cbbSMatt Barden boolean_t expect_success = (idx < numsids);
45*f37b3cbbSMatt Barden ksid_t *ks;
46*f37b3cbbSMatt Barden
47*f37b3cbbSMatt Barden ksl->ksl_nsid = numsids;
48*f37b3cbbSMatt Barden
49*f37b3cbbSMatt Barden start = gethrtime();
50*f37b3cbbSMatt Barden if (pid) {
51*f37b3cbbSMatt Barden /*
52*f37b3cbbSMatt Barden * Only the first savenum entries are sorted,
53*f37b3cbbSMatt Barden * but ksl_sorted is only used when numsids > cutoff.
54*f37b3cbbSMatt Barden * Use ksl_sorted when idx is among them
55*f37b3cbbSMatt Barden */
56*f37b3cbbSMatt Barden if (numsids <= ksl_bin_search_cutoff)
57*f37b3cbbSMatt Barden id = ksl->ksl_sids[idx].ks_id;
58*f37b3cbbSMatt Barden else if (idx >= savenum)
59*f37b3cbbSMatt Barden id = bad_ksids[idx - savenum].ks_id;
60*f37b3cbbSMatt Barden else
61*f37b3cbbSMatt Barden id = ksl->ksl_sorted[idx]->ks_id;
62*f37b3cbbSMatt Barden
63*f37b3cbbSMatt Barden for (i = 0; i < iters; i++) {
64*f37b3cbbSMatt Barden success += (ksidlist_has_pid(ksl, id) ==
65*f37b3cbbSMatt Barden expect_success) ? 1 : 0;
66*f37b3cbbSMatt Barden }
67*f37b3cbbSMatt Barden } else {
68*f37b3cbbSMatt Barden if (idx >= savenum)
69*f37b3cbbSMatt Barden ks = &bad_ksids[idx - savenum];
70*f37b3cbbSMatt Barden else
71*f37b3cbbSMatt Barden ks = &ksl->ksl_sids[idx];
72*f37b3cbbSMatt Barden
73*f37b3cbbSMatt Barden for (i = 0; i < iters; i++) {
74*f37b3cbbSMatt Barden success += (ksidlist_has_sid(ksl,
75*f37b3cbbSMatt Barden ksid_getdomain(ks), ks->ks_rid) ==
76*f37b3cbbSMatt Barden expect_success) ? 1 : 0;
77*f37b3cbbSMatt Barden }
78*f37b3cbbSMatt Barden }
79*f37b3cbbSMatt Barden end = gethrtime();
80*f37b3cbbSMatt Barden
81*f37b3cbbSMatt Barden if (iters > 1) {
82*f37b3cbbSMatt Barden printf("avg time to %s %s in %d sids "
83*f37b3cbbSMatt Barden "over %d iterations: %llu\n",
84*f37b3cbbSMatt Barden (expect_success) ? "find" : "not find",
85*f37b3cbbSMatt Barden (pid) ? "pid" : "sid", numsids, iters,
86*f37b3cbbSMatt Barden (end - start) / iters);
87*f37b3cbbSMatt Barden }
88*f37b3cbbSMatt Barden
89*f37b3cbbSMatt Barden ksl->ksl_nsid = savenum;
90*f37b3cbbSMatt Barden return (success == iters);
91*f37b3cbbSMatt Barden }
92*f37b3cbbSMatt Barden
93*f37b3cbbSMatt Barden void
usage(char * prog)94*f37b3cbbSMatt Barden usage(char *prog)
95*f37b3cbbSMatt Barden {
96*f37b3cbbSMatt Barden fprintf(stderr, "usage: %s [num sids] [num iters]\n", prog);
97*f37b3cbbSMatt Barden }
98*f37b3cbbSMatt Barden
99*f37b3cbbSMatt Barden int
main(int argc,char * argv[])100*f37b3cbbSMatt Barden main(int argc, char *argv[])
101*f37b3cbbSMatt Barden {
102*f37b3cbbSMatt Barden credsid_t *kcr;
103*f37b3cbbSMatt Barden ksidlist_t *ksl;
104*f37b3cbbSMatt Barden uint64_t num_failures = 0;
105*f37b3cbbSMatt Barden uint32_t i, j, numsids, iters;
106*f37b3cbbSMatt Barden boolean_t retry;
107*f37b3cbbSMatt Barden
108*f37b3cbbSMatt Barden if (argc > 1) {
109*f37b3cbbSMatt Barden errno = 0;
110*f37b3cbbSMatt Barden numsids = strtoul(argv[1], NULL, 0);
111*f37b3cbbSMatt Barden if (errno != 0) {
112*f37b3cbbSMatt Barden fprintf(stderr, "error decoding numsids (%s): \n",
113*f37b3cbbSMatt Barden argv[1]);
114*f37b3cbbSMatt Barden usage(argv[0]);
115*f37b3cbbSMatt Barden perror(argv[0]);
116*f37b3cbbSMatt Barden return (errno);
117*f37b3cbbSMatt Barden }
118*f37b3cbbSMatt Barden } else {
119*f37b3cbbSMatt Barden numsids = DEFAULT_NUMSIDS;
120*f37b3cbbSMatt Barden }
121*f37b3cbbSMatt Barden
122*f37b3cbbSMatt Barden if (argc > 2) {
123*f37b3cbbSMatt Barden iters = strtoul(argv[2], NULL, 0);
124*f37b3cbbSMatt Barden if (errno != 0) {
125*f37b3cbbSMatt Barden fprintf(stderr, "error decoding iters (%s): \n",
126*f37b3cbbSMatt Barden argv[2]);
127*f37b3cbbSMatt Barden usage(argv[0]);
128*f37b3cbbSMatt Barden perror(argv[0]);
129*f37b3cbbSMatt Barden return (errno);
130*f37b3cbbSMatt Barden }
131*f37b3cbbSMatt Barden } else {
132*f37b3cbbSMatt Barden iters = DEFAULT_ITERS;
133*f37b3cbbSMatt Barden }
134*f37b3cbbSMatt Barden
135*f37b3cbbSMatt Barden if (numsids < 1 || iters < 1) {
136*f37b3cbbSMatt Barden fprintf(stderr, "both numsids and iters "
137*f37b3cbbSMatt Barden "need to be at least 1\n");
138*f37b3cbbSMatt Barden usage(argv[0]);
139*f37b3cbbSMatt Barden return (2);
140*f37b3cbbSMatt Barden }
141*f37b3cbbSMatt Barden
142*f37b3cbbSMatt Barden /* create MAX_DOMAINS random SIDs */
143*f37b3cbbSMatt Barden for (i = 0; i < MAX_DOMAINS; i++) {
144*f37b3cbbSMatt Barden (void) snprintf(ksid_sids[i], sizeof (ksid_sids[0]),
145*f37b3cbbSMatt Barden "S-1-5-21-%u-%u-%u",
146*f37b3cbbSMatt Barden arc4random(), arc4random(), arc4random());
147*f37b3cbbSMatt Barden }
148*f37b3cbbSMatt Barden
149*f37b3cbbSMatt Barden /* create two unique SIDs for negative testing */
150*f37b3cbbSMatt Barden for (j = MAX_DOMAINS; j < MAX_DOMAINS+2; j++) {
151*f37b3cbbSMatt Barden do {
152*f37b3cbbSMatt Barden retry = B_FALSE;
153*f37b3cbbSMatt Barden (void) snprintf(ksid_sids[j], sizeof (ksid_sids[0]),
154*f37b3cbbSMatt Barden "S-1-5-21-%u-%u-%u",
155*f37b3cbbSMatt Barden arc4random(), arc4random(), arc4random());
156*f37b3cbbSMatt Barden for (i = 0; i < MAX_DOMAINS; i++) {
157*f37b3cbbSMatt Barden if (strncmp(ksid_sids[i], ksid_sids[j],
158*f37b3cbbSMatt Barden sizeof (ksid_sids[0])) == 0) {
159*f37b3cbbSMatt Barden retry = B_TRUE;
160*f37b3cbbSMatt Barden break;
161*f37b3cbbSMatt Barden }
162*f37b3cbbSMatt Barden }
163*f37b3cbbSMatt Barden } while (retry);
164*f37b3cbbSMatt Barden }
165*f37b3cbbSMatt Barden
166*f37b3cbbSMatt Barden ksl = calloc(1, KSIDLIST_MEM(numsids));
167*f37b3cbbSMatt Barden ksl->ksl_ref = 1;
168*f37b3cbbSMatt Barden ksl->ksl_nsid = numsids;
169*f37b3cbbSMatt Barden ksl->ksl_neid = 0;
170*f37b3cbbSMatt Barden
171*f37b3cbbSMatt Barden bad_ksids = malloc(sizeof (ksid_t) * numsids);
172*f37b3cbbSMatt Barden
173*f37b3cbbSMatt Barden /* initialize numsids random sids and ids in the sidlist */
174*f37b3cbbSMatt Barden for (i = 0; i < numsids; i++) {
175*f37b3cbbSMatt Barden uint32_t idx = arc4random_uniform(MAX_DOMAINS);
176*f37b3cbbSMatt Barden
177*f37b3cbbSMatt Barden ksl->ksl_sids[i].ks_id = arc4random();
178*f37b3cbbSMatt Barden ksl->ksl_sids[i].ks_rid = arc4random();
179*f37b3cbbSMatt Barden ksl->ksl_sids[i].ks_domain = ksid_lookupdomain(ksid_sids[idx]);
180*f37b3cbbSMatt Barden ksl->ksl_sids[i].ks_attr = 0;
181*f37b3cbbSMatt Barden }
182*f37b3cbbSMatt Barden
183*f37b3cbbSMatt Barden /*
184*f37b3cbbSMatt Barden * create numsids random sids, whose sids and ids aren't in
185*f37b3cbbSMatt Barden * the sidlist for negative testing
186*f37b3cbbSMatt Barden */
187*f37b3cbbSMatt Barden for (i = 0; i < numsids; i++) {
188*f37b3cbbSMatt Barden bad_ksids[i].ks_attr = 0;
189*f37b3cbbSMatt Barden bad_ksids[i].ks_rid = arc4random();
190*f37b3cbbSMatt Barden bad_ksids[i].ks_domain =
191*f37b3cbbSMatt Barden ksid_lookupdomain(ksid_sids[MAX_DOMAINS +
192*f37b3cbbSMatt Barden (arc4random() % 2)]);
193*f37b3cbbSMatt Barden
194*f37b3cbbSMatt Barden do {
195*f37b3cbbSMatt Barden retry = B_FALSE;
196*f37b3cbbSMatt Barden bad_ksids[i].ks_id = arc4random();
197*f37b3cbbSMatt Barden for (j = 0; j < numsids; j++) {
198*f37b3cbbSMatt Barden if (ksl->ksl_sids[j].ks_id ==
199*f37b3cbbSMatt Barden bad_ksids[i].ks_id) {
200*f37b3cbbSMatt Barden retry = B_TRUE;
201*f37b3cbbSMatt Barden break;
202*f37b3cbbSMatt Barden }
203*f37b3cbbSMatt Barden }
204*f37b3cbbSMatt Barden } while (retry);
205*f37b3cbbSMatt Barden }
206*f37b3cbbSMatt Barden
207*f37b3cbbSMatt Barden kcr = kcrsid_setsidlist(NULL, ksl);
208*f37b3cbbSMatt Barden
209*f37b3cbbSMatt Barden /* run tests */
210*f37b3cbbSMatt Barden for (i = 1; i <= numsids; i++) {
211*f37b3cbbSMatt Barden uint32_t s_idx = arc4random_uniform(i);
212*f37b3cbbSMatt Barden uint32_t f_idx = numsids + i - 1;
213*f37b3cbbSMatt Barden
214*f37b3cbbSMatt Barden if (!run_test(ksl, s_idx, i, iters, B_FALSE)) {
215*f37b3cbbSMatt Barden fprintf(stderr, "Sid search failed unexpectedly: "
216*f37b3cbbSMatt Barden "numsids %u\n", i);
217*f37b3cbbSMatt Barden fprintf(stderr, "Bad SID: id %u rid %u domain %s\n",
218*f37b3cbbSMatt Barden ksl->ksl_sids[s_idx].ks_id,
219*f37b3cbbSMatt Barden ksl->ksl_sids[s_idx].ks_rid,
220*f37b3cbbSMatt Barden ksid_getdomain(&ksl->ksl_sids[s_idx]));
221*f37b3cbbSMatt Barden num_failures++;
222*f37b3cbbSMatt Barden }
223*f37b3cbbSMatt Barden if (!run_test(ksl, s_idx, i, iters, B_TRUE)) {
224*f37b3cbbSMatt Barden fprintf(stderr, "Pid search failed unexpectedly: "
225*f37b3cbbSMatt Barden "numsids %u\n", i);
226*f37b3cbbSMatt Barden fprintf(stderr, "Bad PID: id %u rid %u domain %s\n",
227*f37b3cbbSMatt Barden ksl->ksl_sorted[s_idx]->ks_id,
228*f37b3cbbSMatt Barden ksl->ksl_sorted[s_idx]->ks_rid,
229*f37b3cbbSMatt Barden ksid_getdomain(ksl->ksl_sorted[s_idx]));
230*f37b3cbbSMatt Barden num_failures++;
231*f37b3cbbSMatt Barden }
232*f37b3cbbSMatt Barden
233*f37b3cbbSMatt Barden if (!run_test(ksl, f_idx, i, iters, B_FALSE)) {
234*f37b3cbbSMatt Barden fprintf(stderr, "Sid search succeeded unexpectedly: "
235*f37b3cbbSMatt Barden "numsids %u\n", i);
236*f37b3cbbSMatt Barden fprintf(stderr, "Bad SID: id %u rid %u domain %s\n",
237*f37b3cbbSMatt Barden ksl->ksl_sids[f_idx].ks_id,
238*f37b3cbbSMatt Barden ksl->ksl_sids[f_idx].ks_rid,
239*f37b3cbbSMatt Barden ksid_getdomain(&ksl->ksl_sids[f_idx]));
240*f37b3cbbSMatt Barden num_failures++;
241*f37b3cbbSMatt Barden }
242*f37b3cbbSMatt Barden if (!run_test(ksl, f_idx, i, iters, B_TRUE)) {
243*f37b3cbbSMatt Barden fprintf(stderr, "Pid search succeeded unexpectedly: "
244*f37b3cbbSMatt Barden "numsids %u\n", i);
245*f37b3cbbSMatt Barden fprintf(stderr, "Bad PID: id %u rid %u domain %s\n",
246*f37b3cbbSMatt Barden ksl->ksl_sids[f_idx].ks_id,
247*f37b3cbbSMatt Barden ksl->ksl_sids[f_idx].ks_rid,
248*f37b3cbbSMatt Barden ksid_getdomain(&ksl->ksl_sids[f_idx]));
249*f37b3cbbSMatt Barden num_failures++;
250*f37b3cbbSMatt Barden }
251*f37b3cbbSMatt Barden }
252*f37b3cbbSMatt Barden
253*f37b3cbbSMatt Barden for (i = 0; i < numsids - 1; i++) {
254*f37b3cbbSMatt Barden if (ksl->ksl_sorted[i]->ks_id > ksl->ksl_sorted[i + 1]->ks_id) {
255*f37b3cbbSMatt Barden fprintf(stderr, "PID %u is not sorted correctly: "
256*f37b3cbbSMatt Barden "%u %u\n", i, ksl->ksl_sorted[i]->ks_id,
257*f37b3cbbSMatt Barden ksl->ksl_sorted[i + 1]->ks_id);
258*f37b3cbbSMatt Barden num_failures++;
259*f37b3cbbSMatt Barden }
260*f37b3cbbSMatt Barden if (ksl->ksl_sids[i].ks_rid > ksl->ksl_sids[i + 1].ks_rid) {
261*f37b3cbbSMatt Barden fprintf(stderr, "RID %u is not sorted correctly: "
262*f37b3cbbSMatt Barden "%u %u\n", i, ksl->ksl_sids[i].ks_rid,
263*f37b3cbbSMatt Barden ksl->ksl_sids[i + 1].ks_rid);
264*f37b3cbbSMatt Barden num_failures++;
265*f37b3cbbSMatt Barden } else if (ksl->ksl_sids[i].ks_rid ==
266*f37b3cbbSMatt Barden ksl->ksl_sids[i + 1].ks_rid &&
267*f37b3cbbSMatt Barden strcmp(ksid_getdomain(&ksl->ksl_sids[i]),
268*f37b3cbbSMatt Barden ksid_getdomain(&ksl->ksl_sids[i + 1])) > 0) {
269*f37b3cbbSMatt Barden fprintf(stderr, "SID %u is not sorted correctly: "
270*f37b3cbbSMatt Barden "%s %s\n", i, ksl->ksl_sids[i].ks_rid,
271*f37b3cbbSMatt Barden ksl->ksl_sids[i + 1].ks_rid);
272*f37b3cbbSMatt Barden num_failures++;
273*f37b3cbbSMatt Barden }
274*f37b3cbbSMatt Barden }
275*f37b3cbbSMatt Barden
276*f37b3cbbSMatt Barden if (num_failures != 0) {
277*f37b3cbbSMatt Barden fprintf(stderr, "%d failures detected; dumping SID table\n",
278*f37b3cbbSMatt Barden num_failures);
279*f37b3cbbSMatt Barden for (i = 0; i < numsids; i++) {
280*f37b3cbbSMatt Barden fprintf(stderr, "SID %u: %s-%u -> %u\n", i,
281*f37b3cbbSMatt Barden ksid_getdomain(&ksl->ksl_sids[i]),
282*f37b3cbbSMatt Barden ksl->ksl_sids[i].ks_rid,
283*f37b3cbbSMatt Barden ksl->ksl_sids[i].ks_id);
284*f37b3cbbSMatt Barden }
285*f37b3cbbSMatt Barden
286*f37b3cbbSMatt Barden for (i = 0; i < numsids; i++) {
287*f37b3cbbSMatt Barden fprintf(stderr, "SID %u: %s-%u -> %u\n",
288*f37b3cbbSMatt Barden i + numsids,
289*f37b3cbbSMatt Barden ksid_getdomain(&bad_ksids[i]),
290*f37b3cbbSMatt Barden bad_ksids[i].ks_rid,
291*f37b3cbbSMatt Barden bad_ksids[i].ks_id);
292*f37b3cbbSMatt Barden }
293*f37b3cbbSMatt Barden
294*f37b3cbbSMatt Barden for (i = 0; i < numsids; i++) {
295*f37b3cbbSMatt Barden fprintf(stderr, "PID %u: %u\n", i,
296*f37b3cbbSMatt Barden ksl->ksl_sorted[i]->ks_id);
297*f37b3cbbSMatt Barden }
298*f37b3cbbSMatt Barden } else {
299*f37b3cbbSMatt Barden printf("all tests completed successfully!\n");
300*f37b3cbbSMatt Barden }
301*f37b3cbbSMatt Barden
302*f37b3cbbSMatt Barden kcrsid_rele(kcr);
303*f37b3cbbSMatt Barden
304*f37b3cbbSMatt Barden return (num_failures);
305*f37b3cbbSMatt Barden }
306