File: | xlators/mount/fuse/src/fuse-helpers.c |
Location: | line 375, column 45 |
Description: | Access to field 'table' results in a dereference of a null pointer (loaded from variable 'parent') |
1 | /* | |||
2 | Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com> | |||
3 | This file is part of GlusterFS. | |||
4 | ||||
5 | This file is licensed to you under your choice of the GNU Lesser | |||
6 | General Public License, version 3 or any later version (LGPLv3 or | |||
7 | later), or the GNU General Public License, version 2 (GPLv2), in all | |||
8 | cases as published by the Free Software Foundation. | |||
9 | */ | |||
10 | #include "fuse-bridge.h" | |||
11 | #if defined(GF_SOLARIS_HOST_OS) | |||
12 | #include <sys/procfs.h> | |||
13 | #else | |||
14 | #include <sys/sysctl.h> | |||
15 | #endif | |||
16 | ||||
17 | #ifndef GF_REQUEST_MAXGROUPS16 | |||
18 | #define GF_REQUEST_MAXGROUPS16 16 | |||
19 | #endif /* GF_REQUEST_MAXGROUPS */ | |||
20 | ||||
21 | static void | |||
22 | fuse_resolve_wipe (fuse_resolve_t *resolve) | |||
23 | { | |||
24 | GF_FREE ((void *)resolve->path)__gf_free ((void *)resolve->path); | |||
25 | ||||
26 | GF_FREE ((void *)resolve->bname)__gf_free ((void *)resolve->bname); | |||
27 | ||||
28 | GF_FREE ((void *)resolve->resolved)__gf_free ((void *)resolve->resolved); | |||
29 | ||||
30 | if (resolve->fd) | |||
31 | fd_unref (resolve->fd); | |||
32 | ||||
33 | loc_wipe (&resolve->resolve_loc); | |||
34 | ||||
35 | if (resolve->hint) { | |||
36 | inode_unref (resolve->hint); | |||
37 | resolve->hint = 0; | |||
38 | } | |||
39 | ||||
40 | if (resolve->parhint) { | |||
41 | inode_unref (resolve->parhint); | |||
42 | resolve->parhint = 0; | |||
43 | } | |||
44 | } | |||
45 | ||||
46 | ||||
47 | void | |||
48 | free_fuse_state (fuse_state_t *state) | |||
49 | { | |||
50 | xlator_t *this = NULL((void*)0); | |||
51 | fuse_private_t *priv = NULL((void*)0); | |||
52 | uint64_t winds = 0; | |||
53 | char switched = 0; | |||
54 | ||||
55 | this = state->this; | |||
56 | ||||
57 | priv = this->private; | |||
58 | ||||
59 | loc_wipe (&state->loc); | |||
60 | ||||
61 | loc_wipe (&state->loc2); | |||
62 | ||||
63 | if (state->xdata) { | |||
64 | dict_unref (state->xdata); | |||
65 | state->xdata = (void *)0xaaaaeeee; | |||
66 | } | |||
67 | if (state->xattr) | |||
68 | dict_unref (state->xattr); | |||
69 | ||||
70 | if (state->name) { | |||
71 | GF_FREE (state->name)__gf_free (state->name); | |||
72 | state->name = NULL((void*)0); | |||
73 | } | |||
74 | if (state->fd) { | |||
75 | fd_unref (state->fd); | |||
76 | state->fd = (void *)0xfdfdfdfd; | |||
77 | } | |||
78 | if (state->finh) { | |||
79 | GF_FREE (state->finh)__gf_free (state->finh); | |||
80 | state->finh = NULL((void*)0); | |||
81 | } | |||
82 | ||||
83 | fuse_resolve_wipe (&state->resolve); | |||
84 | fuse_resolve_wipe (&state->resolve2); | |||
85 | ||||
86 | pthread_mutex_lock (&priv->sync_mutex); | |||
87 | { | |||
88 | winds = --state->active_subvol->winds; | |||
89 | switched = state->active_subvol->switched; | |||
90 | } | |||
91 | pthread_mutex_unlock (&priv->sync_mutex); | |||
92 | ||||
93 | if ((winds == 0) && (switched)) { | |||
94 | xlator_notify (state->active_subvol, GF_EVENT_PARENT_DOWN, | |||
95 | state->active_subvol, NULL((void*)0)); | |||
96 | } | |||
97 | ||||
98 | #ifdef DEBUG | |||
99 | memset (state, 0x90, sizeof (*state)); | |||
100 | #endif | |||
101 | GF_FREE (state)__gf_free (state); | |||
102 | state = NULL((void*)0); | |||
103 | } | |||
104 | ||||
105 | ||||
106 | fuse_state_t * | |||
107 | get_fuse_state (xlator_t *this, fuse_in_header_t *finh) | |||
108 | { | |||
109 | fuse_state_t *state = NULL((void*)0); | |||
110 | xlator_t *active_subvol = NULL((void*)0); | |||
111 | fuse_private_t *priv = NULL((void*)0); | |||
112 | ||||
113 | state = (void *)GF_CALLOC (1, sizeof (*state),__gf_calloc (1, sizeof (*state), gf_fuse_mt_fuse_state_t) | |||
114 | gf_fuse_mt_fuse_state_t)__gf_calloc (1, sizeof (*state), gf_fuse_mt_fuse_state_t); | |||
115 | if (!state) | |||
116 | return NULL((void*)0); | |||
117 | ||||
118 | state->this = THIS(*__glusterfs_this_location()); | |||
119 | priv = this->private; | |||
120 | ||||
121 | pthread_mutex_lock (&priv->sync_mutex); | |||
122 | { | |||
123 | active_subvol = fuse_active_subvol (state->this); | |||
124 | active_subvol->winds++; | |||
125 | } | |||
126 | pthread_mutex_unlock (&priv->sync_mutex); | |||
127 | ||||
128 | state->active_subvol = active_subvol; | |||
129 | state->itable = active_subvol->itable; | |||
130 | ||||
131 | state->pool = this->ctx->pool; | |||
132 | state->finh = finh; | |||
133 | state->this = this; | |||
134 | ||||
135 | LOCK_INIT (&state->lock)pthread_spin_init (&state->lock, 0); | |||
136 | ||||
137 | return state; | |||
138 | } | |||
139 | ||||
140 | ||||
141 | void | |||
142 | frame_fill_groups (call_frame_t *frame) | |||
143 | { | |||
144 | #if defined(GF_LINUX_HOST_OS1) | |||
145 | char filename[32]; | |||
146 | char line[4096]; | |||
147 | char *ptr = NULL((void*)0); | |||
148 | FILE *fp = NULL((void*)0); | |||
149 | int idx = 0; | |||
150 | long int id = 0; | |||
151 | char *saveptr = NULL((void*)0); | |||
152 | char *endptr = NULL((void*)0); | |||
153 | int ret = 0; | |||
154 | ||||
155 | ret = snprintf (filename, sizeof filename, "/proc/%d/status", frame->root->pid); | |||
156 | if (ret >= sizeof filename) | |||
157 | goto out; | |||
158 | ||||
159 | fp = fopen (filename, "r"); | |||
160 | if (!fp) | |||
161 | goto out; | |||
162 | ||||
163 | while ((ptr = fgets (line, sizeof line, fp))) { | |||
164 | if (strncmp (ptr, "Groups:", 7) != 0) | |||
165 | continue; | |||
166 | ||||
167 | ptr = line + 8; | |||
168 | ||||
169 | for (ptr = strtok_r (ptr, " \t\r\n", &saveptr); | |||
170 | ptr; | |||
171 | ptr = strtok_r (NULL((void*)0), " \t\r\n", &saveptr)) { | |||
172 | errno(*__errno_location ()) = 0; | |||
173 | id = strtol (ptr, &endptr, 0); | |||
174 | if (errno(*__errno_location ()) == ERANGE34) | |||
175 | break; | |||
176 | if (!endptr || *endptr) | |||
177 | break; | |||
178 | frame->root->groups[idx++] = id; | |||
179 | if (idx == GF_MAX_AUX_GROUPS200) | |||
180 | break; | |||
181 | } | |||
182 | ||||
183 | frame->root->ngrps = idx; | |||
184 | break; | |||
185 | } | |||
186 | out: | |||
187 | if (fp) | |||
188 | fclose (fp); | |||
189 | #elif defined(GF_SOLARIS_HOST_OS) | |||
190 | char filename[32]; | |||
191 | char scratch[128]; | |||
192 | prcred_t *prcred = (prcred_t *) scratch; | |||
193 | FILE *fp = NULL((void*)0); | |||
194 | int ret = 0; | |||
195 | ||||
196 | ret = snprintf (filename, sizeof filename, | |||
197 | "/proc/%d/cred", frame->root->pid); | |||
198 | ||||
199 | if (ret < sizeof filename) { | |||
200 | fp = fopen (filename, "r"); | |||
201 | if (fp != NULL((void*)0)) { | |||
202 | if (fgets (scratch, sizeof scratch, fp) != NULL((void*)0)) { | |||
203 | frame->root->ngrps = MIN(prcred->pr_ngroups, | |||
204 | GF_REQUEST_MAXGROUPS16); | |||
205 | } | |||
206 | fclose (fp); | |||
207 | } | |||
208 | } | |||
209 | #elif defined(CTL_KERN) /* DARWIN and *BSD */ | |||
210 | /* | |||
211 | N.B. CTL_KERN is an enum on Linux. (Meaning, if it's not | |||
212 | obvious, that it's not subject to preprocessor directives | |||
213 | like '#if defined'.) | |||
214 | Unlike Linux, on Mac OS and the BSDs it is a #define. We | |||
215 | could test to see that KERN_PROC is defined, but, barring any | |||
216 | evidence to the contrary, I think that's overkill. | |||
217 | We might also test that GF_DARWIN_HOST_OS is defined, why | |||
218 | limit this to just Mac OS. It's equally valid for the BSDs | |||
219 | and we do have people building on NetBSD and FreeBSD. | |||
220 | */ | |||
221 | int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, frame->root->pid }; | |||
222 | size_t namelen = sizeof name / sizeof name[0]; | |||
223 | struct kinfo_proc kp; | |||
224 | size_t kplen = sizeof(kp); | |||
225 | int i, ngroups; | |||
226 | ||||
227 | if (sysctl(name, namelen, &kp, &kplen, NULL((void*)0), 0) != 0) | |||
228 | return; | |||
229 | ngroups = MIN(kp.kp_eproc.e_ucred.cr_ngroups, GF_REQUEST_MAXGROUPS16); | |||
230 | for (i = 0; i < ngroups; i++) | |||
231 | frame->root->groups[i] = kp.kp_eproc.e_ucred.cr_groups[i]; | |||
232 | frame->root->ngrps = ngroups; | |||
233 | #else | |||
234 | frame->root->ngrps = 0; | |||
235 | #endif /* GF_LINUX_HOST_OS */ | |||
236 | } | |||
237 | ||||
238 | /* | |||
239 | * Get the groups for the PID associated with this frame. If enabled, | |||
240 | * use the gid cache to reduce group list collection. | |||
241 | */ | |||
242 | static void get_groups(fuse_private_t *priv, call_frame_t *frame) | |||
243 | { | |||
244 | int i; | |||
245 | const gid_list_t *gl; | |||
246 | gid_list_t agl; | |||
247 | ||||
248 | if (-1 == priv->gid_cache_timeout) { | |||
249 | frame->root->ngrps = 0; | |||
250 | return; | |||
251 | } | |||
252 | ||||
253 | if (!priv->gid_cache_timeout) { | |||
254 | frame_fill_groups(frame); | |||
255 | return; | |||
256 | } | |||
257 | ||||
258 | gl = gid_cache_lookup(&priv->gid_cache, frame->root->pid); | |||
259 | if (gl) { | |||
260 | frame->root->ngrps = gl->gl_count; | |||
261 | for (i = 0; i < gl->gl_count; i++) | |||
262 | frame->root->groups[i] = gl->gl_list[i]; | |||
263 | gid_cache_release(&priv->gid_cache, gl); | |||
264 | return; | |||
265 | } | |||
266 | ||||
267 | frame_fill_groups (frame); | |||
268 | ||||
269 | agl.gl_id = frame->root->pid; | |||
270 | agl.gl_count = frame->root->ngrps; | |||
271 | agl.gl_list = GF_CALLOC(frame->root->ngrps, sizeof(gid_t),__gf_calloc (frame->root->ngrps, sizeof(gid_t), gf_fuse_mt_gids_t ) | |||
272 | gf_fuse_mt_gids_t)__gf_calloc (frame->root->ngrps, sizeof(gid_t), gf_fuse_mt_gids_t ); | |||
273 | if (!agl.gl_list) | |||
274 | return; | |||
275 | ||||
276 | for (i = 0; i < frame->root->ngrps; i++) | |||
277 | agl.gl_list[i] = frame->root->groups[i]; | |||
278 | ||||
279 | if (gid_cache_add(&priv->gid_cache, &agl) != 1) | |||
280 | GF_FREE(agl.gl_list)__gf_free (agl.gl_list); | |||
281 | } | |||
282 | ||||
283 | call_frame_t * | |||
284 | get_call_frame_for_req (fuse_state_t *state) | |||
285 | { | |||
286 | call_pool_t *pool = NULL((void*)0); | |||
287 | fuse_in_header_t *finh = NULL((void*)0); | |||
288 | call_frame_t *frame = NULL((void*)0); | |||
289 | xlator_t *this = NULL((void*)0); | |||
290 | fuse_private_t *priv = NULL((void*)0); | |||
291 | ||||
292 | pool = state->pool; | |||
293 | finh = state->finh; | |||
294 | this = state->this; | |||
295 | priv = this->private; | |||
296 | ||||
297 | frame = create_frame (this, pool); | |||
298 | if (!frame) | |||
299 | return NULL((void*)0); | |||
300 | ||||
301 | if (finh) { | |||
302 | frame->root->uid = finh->uid; | |||
303 | frame->root->gid = finh->gid; | |||
304 | frame->root->pid = finh->pid; | |||
305 | frame->root->unique = finh->unique; | |||
306 | set_lk_owner_from_uint64 (&frame->root->lk_owner, | |||
307 | state->lk_owner); | |||
308 | } | |||
309 | ||||
310 | get_groups(priv, frame); | |||
311 | ||||
312 | if (priv && priv->client_pid_set) | |||
313 | frame->root->pid = priv->client_pid; | |||
314 | ||||
315 | frame->root->type = GF_OP_TYPE_FOP; | |||
316 | ||||
317 | return frame; | |||
318 | } | |||
319 | ||||
320 | ||||
321 | inode_t * | |||
322 | fuse_ino_to_inode (uint64_t ino, xlator_t *fuse) | |||
323 | { | |||
324 | inode_t *inode = NULL((void*)0); | |||
325 | xlator_t *active_subvol = NULL((void*)0); | |||
326 | ||||
327 | if (ino == 1) { | |||
328 | active_subvol = fuse_active_subvol (fuse); | |||
329 | if (active_subvol) | |||
330 | inode = active_subvol->itable->root; | |||
331 | } else { | |||
332 | inode = (inode_t *) (unsigned long) ino; | |||
333 | inode_ref (inode); | |||
334 | } | |||
335 | ||||
336 | return inode; | |||
337 | } | |||
338 | ||||
339 | uint64_t | |||
340 | inode_to_fuse_nodeid (inode_t *inode) | |||
341 | { | |||
342 | if (!inode) | |||
343 | return 0; | |||
344 | if (__is_root_gfid (inode->gfid)) | |||
345 | return 1; | |||
346 | ||||
347 | return (unsigned long) inode; | |||
348 | } | |||
349 | ||||
350 | ||||
351 | GF_MUST_CHECK__attribute__((warn_unused_result)) int32_t | |||
352 | fuse_loc_fill (loc_t *loc, fuse_state_t *state, ino_t ino, | |||
353 | ino_t par, const char *name) | |||
354 | { | |||
355 | inode_t *inode = NULL((void*)0); | |||
356 | inode_t *parent = NULL((void*)0); | |||
357 | int32_t ret = -1; | |||
358 | char *path = NULL((void*)0); | |||
359 | uuid_t null_gfid = {0,}; | |||
360 | ||||
361 | /* resistance against multiple invocation of loc_fill not to get | |||
362 | reference leaks via inode_search() */ | |||
363 | ||||
364 | if (name) { | |||
| ||||
365 | parent = loc->parent; | |||
366 | if (!parent) { | |||
367 | parent = fuse_ino_to_inode (par, state->this); | |||
368 | loc->parent = parent; | |||
369 | if (parent) | |||
370 | uuid_copy (loc->pargfid, parent->gfid); | |||
371 | } | |||
372 | ||||
373 | inode = loc->inode; | |||
374 | if (!inode) { | |||
375 | inode = inode_grep (parent->table, parent, name); | |||
| ||||
376 | loc->inode = inode; | |||
377 | } | |||
378 | ||||
379 | ret = inode_path (parent, name, &path); | |||
380 | if (ret <= 0) { | |||
381 | gf_log ("glusterfs-fuse", GF_LOG_DEBUG,do { do { if (0) printf ("inode_path failed for %s/%s", (parent )?uuid_utoa (parent->gfid):"0", name); } while (0); _gf_log ("glusterfs-fuse", "fuse-helpers.c", __FUNCTION__, 383, GF_LOG_DEBUG , "inode_path failed for %s/%s", (parent)?uuid_utoa (parent-> gfid):"0", name); } while (0) | |||
382 | "inode_path failed for %s/%s",do { do { if (0) printf ("inode_path failed for %s/%s", (parent )?uuid_utoa (parent->gfid):"0", name); } while (0); _gf_log ("glusterfs-fuse", "fuse-helpers.c", __FUNCTION__, 383, GF_LOG_DEBUG , "inode_path failed for %s/%s", (parent)?uuid_utoa (parent-> gfid):"0", name); } while (0) | |||
383 | (parent)?uuid_utoa (parent->gfid):"0", name)do { do { if (0) printf ("inode_path failed for %s/%s", (parent )?uuid_utoa (parent->gfid):"0", name); } while (0); _gf_log ("glusterfs-fuse", "fuse-helpers.c", __FUNCTION__, 383, GF_LOG_DEBUG , "inode_path failed for %s/%s", (parent)?uuid_utoa (parent-> gfid):"0", name); } while (0); | |||
384 | goto fail; | |||
385 | } | |||
386 | loc->path = path; | |||
387 | } else { | |||
388 | inode = loc->inode; | |||
389 | if (!inode) { | |||
390 | inode = fuse_ino_to_inode (ino, state->this); | |||
391 | loc->inode = inode; | |||
392 | if (inode) | |||
393 | uuid_copy (loc->gfid, inode->gfid); | |||
394 | } | |||
395 | ||||
396 | parent = loc->parent; | |||
397 | if (!parent) { | |||
398 | parent = inode_parent (inode, null_gfid, NULL((void*)0)); | |||
399 | loc->parent = parent; | |||
400 | if (parent) | |||
401 | uuid_copy (loc->pargfid, parent->gfid); | |||
402 | ||||
403 | } | |||
404 | ||||
405 | ret = inode_path (inode, NULL((void*)0), &path); | |||
406 | if (ret <= 0) { | |||
407 | gf_log ("glusterfs-fuse", GF_LOG_DEBUG,do { do { if (0) printf ("inode_path failed for %s", (inode) ? uuid_utoa (inode->gfid) : "0"); } while (0); _gf_log ("glusterfs-fuse" , "fuse-helpers.c", __FUNCTION__, 409, GF_LOG_DEBUG, "inode_path failed for %s" , (inode) ? uuid_utoa (inode->gfid) : "0"); } while (0) | |||
408 | "inode_path failed for %s",do { do { if (0) printf ("inode_path failed for %s", (inode) ? uuid_utoa (inode->gfid) : "0"); } while (0); _gf_log ("glusterfs-fuse" , "fuse-helpers.c", __FUNCTION__, 409, GF_LOG_DEBUG, "inode_path failed for %s" , (inode) ? uuid_utoa (inode->gfid) : "0"); } while (0) | |||
409 | (inode) ? uuid_utoa (inode->gfid) : "0")do { do { if (0) printf ("inode_path failed for %s", (inode) ? uuid_utoa (inode->gfid) : "0"); } while (0); _gf_log ("glusterfs-fuse" , "fuse-helpers.c", __FUNCTION__, 409, GF_LOG_DEBUG, "inode_path failed for %s" , (inode) ? uuid_utoa (inode->gfid) : "0"); } while (0); | |||
410 | goto fail; | |||
411 | } | |||
412 | loc->path = path; | |||
413 | } | |||
414 | ||||
415 | if (loc->path) { | |||
416 | loc->name = strrchr (loc->path, '/'); | |||
417 | if (loc->name) | |||
418 | loc->name++; | |||
419 | else | |||
420 | loc->name = ""; | |||
421 | } | |||
422 | ||||
423 | if ((ino != 1) && (parent == NULL((void*)0))) { | |||
424 | gf_log ("fuse-bridge", GF_LOG_DEBUG,do { do { if (0) printf ("failed to search parent for %""ll" "d" "/%s (%""ll" "d"")", (ino_t)par, name, (ino_t)ino); } while ( 0); _gf_log ("fuse-bridge", "fuse-helpers.c", __FUNCTION__, 426 , GF_LOG_DEBUG, "failed to search parent for %""ll" "d""/%s (%" "ll" "d"")", (ino_t)par, name, (ino_t)ino); } while (0) | |||
425 | "failed to search parent for %"PRId64"/%s (%"PRId64")",do { do { if (0) printf ("failed to search parent for %""ll" "d" "/%s (%""ll" "d"")", (ino_t)par, name, (ino_t)ino); } while ( 0); _gf_log ("fuse-bridge", "fuse-helpers.c", __FUNCTION__, 426 , GF_LOG_DEBUG, "failed to search parent for %""ll" "d""/%s (%" "ll" "d"")", (ino_t)par, name, (ino_t)ino); } while (0) | |||
426 | (ino_t)par, name, (ino_t)ino)do { do { if (0) printf ("failed to search parent for %""ll" "d" "/%s (%""ll" "d"")", (ino_t)par, name, (ino_t)ino); } while ( 0); _gf_log ("fuse-bridge", "fuse-helpers.c", __FUNCTION__, 426 , GF_LOG_DEBUG, "failed to search parent for %""ll" "d""/%s (%" "ll" "d"")", (ino_t)par, name, (ino_t)ino); } while (0); | |||
427 | ret = -1; | |||
428 | goto fail; | |||
429 | } | |||
430 | ret = 0; | |||
431 | fail: | |||
432 | /* this should not happen as inode_path returns -1 when buf is NULL | |||
433 | for sure */ | |||
434 | if (path && !loc->path) | |||
435 | GF_FREE (path)__gf_free (path); | |||
436 | return ret; | |||
437 | } | |||
438 | ||||
439 | /* Use the same logic as the Linux NFS-client */ | |||
440 | #define GF_FUSE_SQUASH_INO(ino)((uint32_t) ino) ^ (ino >> 32) ((uint32_t) ino) ^ (ino >> 32) | |||
441 | ||||
442 | /* courtesy of folly */ | |||
443 | void | |||
444 | gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa, gf_boolean_t enable_ino32) | |||
445 | { | |||
446 | if (enable_ino32) | |||
447 | fa->ino = GF_FUSE_SQUASH_INO(st->ia_ino)((uint32_t) st->ia_ino) ^ (st->ia_ino >> 32); | |||
448 | else | |||
449 | fa->ino = st->ia_ino; | |||
450 | ||||
451 | fa->size = st->ia_size; | |||
452 | fa->blocks = st->ia_blocks; | |||
453 | fa->atime = st->ia_atime; | |||
454 | fa->mtime = st->ia_mtime; | |||
455 | fa->ctime = st->ia_ctime; | |||
456 | fa->atimensec = st->ia_atime_nsec; | |||
457 | fa->mtimensec = st->ia_mtime_nsec; | |||
458 | fa->ctimensec = st->ia_ctime_nsec; | |||
459 | fa->mode = st_mode_from_ia (st->ia_prot, st->ia_type); | |||
460 | fa->nlink = st->ia_nlink; | |||
461 | fa->uid = st->ia_uid; | |||
462 | fa->gid = st->ia_gid; | |||
463 | fa->rdev = makedev (ia_major (st->ia_rdev),gnu_dev_makedev (ia_major (st->ia_rdev), ia_minor (st-> ia_rdev)) | |||
464 | ia_minor (st->ia_rdev))gnu_dev_makedev (ia_major (st->ia_rdev), ia_minor (st-> ia_rdev)); | |||
465 | #if FUSE_KERNEL_MINOR_VERSION13 >= 9 | |||
466 | fa->blksize = st->ia_blksize; | |||
467 | #endif | |||
468 | #ifdef GF_DARWIN_HOST_OS | |||
469 | fa->crtime = (uint64_t)-1; | |||
470 | fa->crtimensec = (uint32_t)-1; | |||
471 | fa->flags = 0; | |||
472 | #endif | |||
473 | } | |||
474 | ||||
475 | void | |||
476 | gf_fuse_fill_dirent (gf_dirent_t *entry, struct fuse_dirent *fde, gf_boolean_t enable_ino32) | |||
477 | { | |||
478 | if (enable_ino32) | |||
479 | fde->ino = GF_FUSE_SQUASH_INO(entry->d_ino)((uint32_t) entry->d_ino) ^ (entry->d_ino >> 32); | |||
480 | else | |||
481 | fde->ino = entry->d_ino; | |||
482 | ||||
483 | fde->off = entry->d_off; | |||
484 | fde->type = entry->d_type; | |||
485 | fde->namelen = strlen (entry->d_name); | |||
486 | strncpy (fde->name, entry->d_name, fde->namelen); | |||
487 | } | |||
488 | ||||
489 | static int | |||
490 | fuse_do_flip_xattr_ns (char *okey, const char *nns, char **nkey) | |||
491 | { | |||
492 | int ret = 0; | |||
493 | char *key = NULL((void*)0); | |||
494 | ||||
495 | okey = strchr (okey, '.'); | |||
496 | GF_ASSERT (okey)do { if (!(okey)) { do { do { if (0) printf ("Assertion failed: " "okey"); } while (0); _gf_log_callingfn ("", "fuse-helpers.c" , __FUNCTION__, 496, GF_LOG_ERROR, "Assertion failed: " "okey" ); } while (0); } } while (0); | |||
497 | ||||
498 | key = GF_CALLOC (1, strlen (nns) + strlen(okey) + 1,__gf_calloc (1, strlen (nns) + strlen(okey) + 1, gf_common_mt_char ) | |||
499 | gf_common_mt_char)__gf_calloc (1, strlen (nns) + strlen(okey) + 1, gf_common_mt_char ); | |||
500 | if (!key) { | |||
501 | ret = -1; | |||
502 | goto out; | |||
503 | } | |||
504 | ||||
505 | strcpy (key, nns); | |||
506 | strcat (key, okey); | |||
507 | ||||
508 | *nkey = key; | |||
509 | ||||
510 | out: | |||
511 | return ret; | |||
512 | } | |||
513 | ||||
514 | static int | |||
515 | fuse_xattr_alloc_default (char *okey, char **nkey) | |||
516 | { | |||
517 | int ret = 0; | |||
518 | ||||
519 | *nkey = gf_strdup (okey); | |||
520 | if (!*nkey) | |||
521 | ret = -1; | |||
522 | return ret; | |||
523 | } | |||
524 | ||||
525 | #define PRIV_XA_NS"trusted" "trusted" | |||
526 | #define UNPRIV_XA_NS"system" "system" | |||
527 | ||||
528 | int | |||
529 | fuse_flip_xattr_ns (fuse_private_t *priv, char *okey, char **nkey) | |||
530 | { | |||
531 | int ret = 0; | |||
532 | gf_boolean_t need_flip = _gf_false; | |||
533 | ||||
534 | switch (priv->client_pid) { | |||
535 | case GF_CLIENT_PID_GSYNCD: | |||
536 | /* valid xattr(s): *xtime, volume-mark* */ | |||
537 | gf_log("glusterfs-fuse", GF_LOG_DEBUG, "PID: %d, checking xattr(s): "do { do { if (0) printf ("PID: %d, checking xattr(s): " "volume-mark*, *xtime" , priv->client_pid); } while (0); _gf_log ("glusterfs-fuse" , "fuse-helpers.c", __FUNCTION__, 538, GF_LOG_DEBUG, "PID: %d, checking xattr(s): " "volume-mark*, *xtime", priv->client_pid); } while (0) | |||
538 | "volume-mark*, *xtime", priv->client_pid)do { do { if (0) printf ("PID: %d, checking xattr(s): " "volume-mark*, *xtime" , priv->client_pid); } while (0); _gf_log ("glusterfs-fuse" , "fuse-helpers.c", __FUNCTION__, 538, GF_LOG_DEBUG, "PID: %d, checking xattr(s): " "volume-mark*, *xtime", priv->client_pid); } while (0); | |||
539 | if ( (strcmp (okey, UNPRIV_XA_NS"system"".glusterfs.volume-mark") == 0) | |||
540 | || (fnmatch (UNPRIV_XA_NS"system"".glusterfs.volume-mark.*", okey, FNM_PERIOD(1 << 2)) == 0) | |||
541 | || (fnmatch (UNPRIV_XA_NS"system"".glusterfs.*.xtime", okey, FNM_PERIOD(1 << 2)) == 0) ) | |||
542 | need_flip = _gf_true; | |||
543 | break; | |||
544 | ||||
545 | case GF_CLIENT_PID_HADOOP: | |||
546 | /* valid xattr(s): pathinfo */ | |||
547 | gf_log("glusterfs-fuse", GF_LOG_DEBUG, "PID: %d, checking xattr(s): "do { do { if (0) printf ("PID: %d, checking xattr(s): " "pathinfo" , priv->client_pid); } while (0); _gf_log ("glusterfs-fuse" , "fuse-helpers.c", __FUNCTION__, 548, GF_LOG_DEBUG, "PID: %d, checking xattr(s): " "pathinfo", priv->client_pid); } while (0) | |||
548 | "pathinfo", priv->client_pid)do { do { if (0) printf ("PID: %d, checking xattr(s): " "pathinfo" , priv->client_pid); } while (0); _gf_log ("glusterfs-fuse" , "fuse-helpers.c", __FUNCTION__, 548, GF_LOG_DEBUG, "PID: %d, checking xattr(s): " "pathinfo", priv->client_pid); } while (0); | |||
549 | if (strcmp (okey, UNPRIV_XA_NS"system"".glusterfs.pathinfo") == 0) | |||
550 | need_flip = _gf_true; | |||
551 | break; | |||
552 | } | |||
553 | ||||
554 | if (need_flip) { | |||
555 | gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "flipping %s to "PRIV_XA_NS" equivalent",do { do { if (0) printf ("flipping %s to ""trusted"" equivalent" , okey); } while (0); _gf_log ("glusterfs-fuse", "fuse-helpers.c" , __FUNCTION__, 556, GF_LOG_DEBUG, "flipping %s to ""trusted" " equivalent", okey); } while (0) | |||
556 | okey)do { do { if (0) printf ("flipping %s to ""trusted"" equivalent" , okey); } while (0); _gf_log ("glusterfs-fuse", "fuse-helpers.c" , __FUNCTION__, 556, GF_LOG_DEBUG, "flipping %s to ""trusted" " equivalent", okey); } while (0); | |||
557 | ret = fuse_do_flip_xattr_ns (okey, PRIV_XA_NS"trusted", nkey); | |||
558 | } else { | |||
559 | /* if we cannot match, continue with what we got */ | |||
560 | ret = fuse_xattr_alloc_default (okey, nkey); | |||
561 | } | |||
562 | ||||
563 | return ret; | |||
564 | } | |||
565 | ||||
566 | int | |||
567 | fuse_ignore_xattr_set (fuse_private_t *priv, char *key) | |||
568 | { | |||
569 | int ret = 0; | |||
570 | ||||
571 | /* don't mess with user namespace */ | |||
572 | if (fnmatch ("user.*", key, FNM_PERIOD(1 << 2)) == 0) | |||
573 | goto out; | |||
574 | ||||
575 | if (priv->client_pid != GF_CLIENT_PID_GSYNCD) | |||
576 | goto out; | |||
577 | ||||
578 | /* trusted NS check */ | |||
579 | if (!((fnmatch ("*.glusterfs.*.xtime", key, FNM_PERIOD(1 << 2)) == 0) | |||
580 | || (fnmatch ("*.glusterfs.volume-mark", | |||
581 | key, FNM_PERIOD(1 << 2)) == 0) | |||
582 | || (fnmatch ("*.glusterfs.volume-mark.*", | |||
583 | key, FNM_PERIOD(1 << 2)) == 0))) | |||
584 | ret = -1; | |||
585 | ||||
586 | out: | |||
587 | gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "%s setxattr: key [%s], "do { do { if (0) printf ("%s setxattr: key [%s], " " client pid [%d]" , (ret ? "disallowing" : "allowing"), key, priv->client_pid ); } while (0); _gf_log ("glusterfs-fuse", "fuse-helpers.c", __FUNCTION__ , 589, GF_LOG_DEBUG, "%s setxattr: key [%s], " " client pid [%d]" , (ret ? "disallowing" : "allowing"), key, priv->client_pid ); } while (0) | |||
588 | " client pid [%d]", (ret ? "disallowing" : "allowing"), key,do { do { if (0) printf ("%s setxattr: key [%s], " " client pid [%d]" , (ret ? "disallowing" : "allowing"), key, priv->client_pid ); } while (0); _gf_log ("glusterfs-fuse", "fuse-helpers.c", __FUNCTION__ , 589, GF_LOG_DEBUG, "%s setxattr: key [%s], " " client pid [%d]" , (ret ? "disallowing" : "allowing"), key, priv->client_pid ); } while (0) | |||
589 | priv->client_pid)do { do { if (0) printf ("%s setxattr: key [%s], " " client pid [%d]" , (ret ? "disallowing" : "allowing"), key, priv->client_pid ); } while (0); _gf_log ("glusterfs-fuse", "fuse-helpers.c", __FUNCTION__ , 589, GF_LOG_DEBUG, "%s setxattr: key [%s], " " client pid [%d]" , (ret ? "disallowing" : "allowing"), key, priv->client_pid ); } while (0); | |||
590 | ||||
591 | return ret; | |||
592 | } |