s3: nmbd: Fix bug 10633 - nmbd denial of service
[samba.git] / source3 / lib / system.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba system utilities
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison  1998-2005
6    Copyright (C) Timur Bakeyev        2005
7    Copyright (C) Bjoern Jacke    2006-2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "system/syslog.h"
25 #include "system/capability.h"
26 #include "system/passwd.h"
27 #include "system/filesys.h"
28 #include "../lib/util/setid.h"
29
30 #ifdef HAVE_SYS_SYSCTL_H
31 #include <sys/sysctl.h>
32 #endif
33
34 #ifdef HAVE_SYS_PRCTL_H
35 #include <sys/prctl.h>
36 #endif
37
38 /*
39    The idea is that this file will eventually have wrappers around all
40    important system calls in samba. The aims are:
41
42    - to enable easier porting by putting OS dependent stuff in here
43
44    - to allow for hooks into other "pseudo-filesystems"
45
46    - to allow easier integration of things like the japanese extensions
47
48    - to support the philosophy of Samba to expose the features of
49      the OS within the SMB model. In general whatever file/printer/variable
50      expansions/etc make sense to the OS should be acceptable to Samba.
51 */
52
53
54
55 /*******************************************************************
56 A read wrapper that will deal with EINTR.
57 ********************************************************************/
58
59 ssize_t sys_read(int fd, void *buf, size_t count)
60 {
61         ssize_t ret;
62
63         do {
64                 ret = read(fd, buf, count);
65 #if defined(EWOULDBLOCK)
66         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
67 #else
68         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
69 #endif
70         return ret;
71 }
72
73 /*******************************************************************
74 A write wrapper that will deal with EINTR.
75 ********************************************************************/
76
77 ssize_t sys_write(int fd, const void *buf, size_t count)
78 {
79         ssize_t ret;
80
81         do {
82                 ret = write(fd, buf, count);
83 #if defined(EWOULDBLOCK)
84         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
85 #else
86         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
87 #endif
88         return ret;
89 }
90
91 /*******************************************************************
92 A writev wrapper that will deal with EINTR.
93 ********************************************************************/
94
95 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
96 {
97         ssize_t ret;
98
99 #if 0
100         /* Try to confuse write_data_iov a bit */
101         if ((random() % 5) == 0) {
102                 return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
103         }
104         if (iov[0].iov_len > 1) {
105                 return sys_write(fd, iov[0].iov_base,
106                                  (random() % (iov[0].iov_len-1)) + 1);
107         }
108 #endif
109
110         do {
111                 ret = writev(fd, iov, iovcnt);
112 #if defined(EWOULDBLOCK)
113         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
114 #else
115         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
116 #endif
117         return ret;
118 }
119
120 /*******************************************************************
121 A pread wrapper that will deal with EINTR
122 ********************************************************************/
123
124 #if defined(HAVE_PREAD)
125 ssize_t sys_pread(int fd, void *buf, size_t count, off_t off)
126 {
127         ssize_t ret;
128
129         do {
130                 ret = pread(fd, buf, count, off);
131         } while (ret == -1 && errno == EINTR);
132         return ret;
133 }
134 #endif
135
136 /*******************************************************************
137 A write wrapper that will deal with EINTR
138 ********************************************************************/
139
140 #if defined(HAVE_PWRITE)
141 ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off)
142 {
143         ssize_t ret;
144
145         do {
146                 ret = pwrite(fd, buf, count, off);
147         } while (ret == -1 && errno == EINTR);
148         return ret;
149 }
150 #endif
151
152 /*******************************************************************
153 A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
154 ********************************************************************/
155
156 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
157 {
158         ssize_t ret;
159
160         do {
161                 ret = send(s, msg, len, flags);
162 #if defined(EWOULDBLOCK)
163         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
164 #else
165         } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
166 #endif
167         return ret;
168 }
169
170 /*******************************************************************
171 A recvfrom wrapper that will deal with EINTR.
172 NB. As used with non-blocking sockets, return on EAGAIN/EWOULDBLOCK
173 ********************************************************************/
174
175 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
176 {
177         ssize_t ret;
178
179         do {
180                 ret = recvfrom(s, buf, len, flags, from, fromlen);
181         } while (ret == -1 && (errno == EINTR));
182         return ret;
183 }
184
185 /*******************************************************************
186 A fcntl wrapper that will deal with EINTR.
187 ********************************************************************/
188
189 int sys_fcntl_ptr(int fd, int cmd, void *arg)
190 {
191         int ret;
192
193         do {
194                 ret = fcntl(fd, cmd, arg);
195         } while (ret == -1 && errno == EINTR);
196         return ret;
197 }
198
199 /*******************************************************************
200 A fcntl wrapper that will deal with EINTR.
201 ********************************************************************/
202
203 int sys_fcntl_long(int fd, int cmd, long arg)
204 {
205         int ret;
206
207         do {
208                 ret = fcntl(fd, cmd, arg);
209         } while (ret == -1 && errno == EINTR);
210         return ret;
211 }
212
213 /****************************************************************************
214  Get/Set all the possible time fields from a stat struct as a timespec.
215 ****************************************************************************/
216
217 static struct timespec get_atimespec(const struct stat *pst)
218 {
219 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
220         struct timespec ret;
221
222         /* Old system - no ns timestamp. */
223         ret.tv_sec = pst->st_atime;
224         ret.tv_nsec = 0;
225         return ret;
226 #else
227 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
228         struct timespec ret;
229         ret.tv_sec = pst->st_atim.tv_sec;
230         ret.tv_nsec = pst->st_atim.tv_nsec;
231         return ret;
232 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
233         struct timespec ret;
234         ret.tv_sec = pst->st_atime;
235         ret.tv_nsec = pst->st_atimensec;
236         return ret;
237 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
238         struct timespec ret;
239         ret.tv_sec = pst->st_atime;
240         ret.tv_nsec = pst->st_atime_n;
241         return ret;
242 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
243         struct timespec ret;
244         ret.tv_sec = pst->st_atime;
245         ret.tv_nsec = pst->st_uatime * 1000;
246         return ret;
247 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
248         return pst->st_atimespec;
249 #else
250 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
251 #endif
252 #endif
253 }
254
255 static struct timespec get_mtimespec(const struct stat *pst)
256 {
257 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
258         struct timespec ret;
259
260         /* Old system - no ns timestamp. */
261         ret.tv_sec = pst->st_mtime;
262         ret.tv_nsec = 0;
263         return ret;
264 #else
265 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
266         struct timespec ret;
267         ret.tv_sec = pst->st_mtim.tv_sec;
268         ret.tv_nsec = pst->st_mtim.tv_nsec;
269         return ret;
270 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
271         struct timespec ret;
272         ret.tv_sec = pst->st_mtime;
273         ret.tv_nsec = pst->st_mtimensec;
274         return ret;
275 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
276         struct timespec ret;
277         ret.tv_sec = pst->st_mtime;
278         ret.tv_nsec = pst->st_mtime_n;
279         return ret;
280 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
281         struct timespec ret;
282         ret.tv_sec = pst->st_mtime;
283         ret.tv_nsec = pst->st_umtime * 1000;
284         return ret;
285 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
286         return pst->st_mtimespec;
287 #else
288 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
289 #endif
290 #endif
291 }
292
293 static struct timespec get_ctimespec(const struct stat *pst)
294 {
295 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
296         struct timespec ret;
297
298         /* Old system - no ns timestamp. */
299         ret.tv_sec = pst->st_ctime;
300         ret.tv_nsec = 0;
301         return ret;
302 #else
303 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
304         struct timespec ret;
305         ret.tv_sec = pst->st_ctim.tv_sec;
306         ret.tv_nsec = pst->st_ctim.tv_nsec;
307         return ret;
308 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
309         struct timespec ret;
310         ret.tv_sec = pst->st_ctime;
311         ret.tv_nsec = pst->st_ctimensec;
312         return ret;
313 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
314         struct timespec ret;
315         ret.tv_sec = pst->st_ctime;
316         ret.tv_nsec = pst->st_ctime_n;
317         return ret;
318 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
319         struct timespec ret;
320         ret.tv_sec = pst->st_ctime;
321         ret.tv_nsec = pst->st_uctime * 1000;
322         return ret;
323 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
324         return pst->st_ctimespec;
325 #else
326 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
327 #endif
328 #endif
329 }
330
331 /****************************************************************************
332  Return the best approximation to a 'create time' under UNIX from a stat
333  structure.
334 ****************************************************************************/
335
336 static struct timespec calc_create_time_stat(const struct stat *st)
337 {
338         struct timespec ret, ret1;
339         struct timespec c_time = get_ctimespec(st);
340         struct timespec m_time = get_mtimespec(st);
341         struct timespec a_time = get_atimespec(st);
342
343         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
344         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
345
346         if(!null_timespec(ret1)) {
347                 return ret1;
348         }
349
350         /*
351          * One of ctime, mtime or atime was zero (probably atime).
352          * Just return MIN(ctime, mtime).
353          */
354         return ret;
355 }
356
357 /****************************************************************************
358  Return the best approximation to a 'create time' under UNIX from a stat_ex
359  structure.
360 ****************************************************************************/
361
362 static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
363 {
364         struct timespec ret, ret1;
365         struct timespec c_time = st->st_ex_ctime;
366         struct timespec m_time = st->st_ex_mtime;
367         struct timespec a_time = st->st_ex_atime;
368
369         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
370         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
371
372         if(!null_timespec(ret1)) {
373                 return ret1;
374         }
375
376         /*
377          * One of ctime, mtime or atime was zero (probably atime).
378          * Just return MIN(ctime, mtime).
379          */
380         return ret;
381 }
382
383 /****************************************************************************
384  Return the 'create time' from a stat struct if it exists (birthtime) or else
385  use the best approximation.
386 ****************************************************************************/
387
388 static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
389                                  bool fake_dir_create_times)
390 {
391         if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
392                 dst->st_ex_btime.tv_sec = 315493200L;          /* 1/1/1980 */
393                 dst->st_ex_btime.tv_nsec = 0;
394         }
395
396         dst->st_ex_calculated_birthtime = false;
397
398 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
399         dst->st_ex_btime = pst->st_birthtimespec;
400 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
401         dst->st_ex_btime.tv_sec = pst->st_birthtime;
402         dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
403 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
404         dst->st_ex_btime.tv_sec = pst->st_birthtime;
405         dst->st_ex_btime.tv_nsec = 0;
406 #else
407         dst->st_ex_btime = calc_create_time_stat(pst);
408         dst->st_ex_calculated_birthtime = true;
409 #endif
410
411         /* Deal with systems that don't initialize birthtime correctly.
412          * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
413          */
414         if (null_timespec(dst->st_ex_btime)) {
415                 dst->st_ex_btime = calc_create_time_stat(pst);
416                 dst->st_ex_calculated_birthtime = true;
417         }
418 }
419
420 /****************************************************************************
421  If we update a timestamp in a stat_ex struct we may have to recalculate
422  the birthtime. For now only implement this for write time, but we may
423  also need to do it for atime and ctime. JRA.
424 ****************************************************************************/
425
426 void update_stat_ex_mtime(struct stat_ex *dst,
427                                 struct timespec write_ts)
428 {
429         dst->st_ex_mtime = write_ts;
430
431         /* We may have to recalculate btime. */
432         if (dst->st_ex_calculated_birthtime) {
433                 dst->st_ex_btime = calc_create_time_stat_ex(dst);
434         }
435 }
436
437 void update_stat_ex_create_time(struct stat_ex *dst,
438                                 struct timespec create_time)
439 {
440         dst->st_ex_btime = create_time;
441         dst->st_ex_calculated_birthtime = false;
442 }
443
444 void init_stat_ex_from_stat (struct stat_ex *dst,
445                             const struct stat *src,
446                             bool fake_dir_create_times)
447 {
448         dst->st_ex_dev = src->st_dev;
449         dst->st_ex_ino = src->st_ino;
450         dst->st_ex_mode = src->st_mode;
451         dst->st_ex_nlink = src->st_nlink;
452         dst->st_ex_uid = src->st_uid;
453         dst->st_ex_gid = src->st_gid;
454         dst->st_ex_rdev = src->st_rdev;
455         dst->st_ex_size = src->st_size;
456         dst->st_ex_atime = get_atimespec(src);
457         dst->st_ex_mtime = get_mtimespec(src);
458         dst->st_ex_ctime = get_ctimespec(src);
459         make_create_timespec(src, dst, fake_dir_create_times);
460 #ifdef HAVE_STAT_ST_BLKSIZE
461         dst->st_ex_blksize = src->st_blksize;
462 #else
463         dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
464 #endif
465
466 #ifdef HAVE_STAT_ST_BLOCKS
467         dst->st_ex_blocks = src->st_blocks;
468 #else
469         dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
470 #endif
471
472 #ifdef HAVE_STAT_ST_FLAGS
473         dst->st_ex_flags = src->st_flags;
474 #else
475         dst->st_ex_flags = 0;
476 #endif
477 }
478
479 /*******************************************************************
480 A stat() wrapper.
481 ********************************************************************/
482
483 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
484              bool fake_dir_create_times)
485 {
486         int ret;
487         struct stat statbuf;
488         ret = stat(fname, &statbuf);
489         if (ret == 0) {
490                 /* we always want directories to appear zero size */
491                 if (S_ISDIR(statbuf.st_mode)) {
492                         statbuf.st_size = 0;
493                 }
494                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
495         }
496         return ret;
497 }
498
499 /*******************************************************************
500  An fstat() wrapper.
501 ********************************************************************/
502
503 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
504 {
505         int ret;
506         struct stat statbuf;
507         ret = fstat(fd, &statbuf);
508         if (ret == 0) {
509                 /* we always want directories to appear zero size */
510                 if (S_ISDIR(statbuf.st_mode)) {
511                         statbuf.st_size = 0;
512                 }
513                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
514         }
515         return ret;
516 }
517
518 /*******************************************************************
519  An lstat() wrapper.
520 ********************************************************************/
521
522 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
523               bool fake_dir_create_times)
524 {
525         int ret;
526         struct stat statbuf;
527         ret = lstat(fname, &statbuf);
528         if (ret == 0) {
529                 /* we always want directories to appear zero size */
530                 if (S_ISDIR(statbuf.st_mode)) {
531                         statbuf.st_size = 0;
532                 }
533                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
534         }
535         return ret;
536 }
537
538 /*******************************************************************
539  An posix_fallocate() wrapper.
540 ********************************************************************/
541 int sys_posix_fallocate(int fd, off_t offset, off_t len)
542 {
543 #if defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_BROKEN_POSIX_FALLOCATE)
544         return posix_fallocate(fd, offset, len);
545 #elif defined(F_RESVSP64)
546         /* this handles XFS on IRIX */
547         struct flock64 fl;
548         off_t new_len = offset + len;
549         int ret;
550         struct stat64 sbuf;
551
552         /* unlikely to get a too large file on a 64bit system but ... */
553         if (new_len < 0)
554                 return EFBIG;
555
556         fl.l_whence = SEEK_SET;
557         fl.l_start = offset;
558         fl.l_len = len;
559
560         ret=fcntl(fd, F_RESVSP64, &fl);
561
562         if (ret != 0)
563                 return errno;
564
565         /* Make sure the file gets enlarged after we allocated space: */
566         fstat64(fd, &sbuf);
567         if (new_len > sbuf.st_size)
568                 ftruncate64(fd, new_len);
569         return 0;
570 #else
571         return ENOSYS;
572 #endif
573 }
574
575 /*******************************************************************
576  An fallocate() function that matches the semantics of the Linux one.
577 ********************************************************************/
578
579 #ifdef HAVE_LINUX_FALLOC_H
580 #include <linux/falloc.h>
581 #endif
582
583 int sys_fallocate(int fd, enum vfs_fallocate_mode mode, off_t offset, off_t len)
584 {
585 #if defined(HAVE_LINUX_FALLOCATE64) || defined(HAVE_LINUX_FALLOCATE)
586         int lmode;
587         switch (mode) {
588         case VFS_FALLOCATE_EXTEND_SIZE:
589                 lmode = 0;
590                 break;
591         case VFS_FALLOCATE_KEEP_SIZE:
592                 lmode = FALLOC_FL_KEEP_SIZE;
593                 break;
594         default:
595                 errno = EINVAL;
596                 return -1;
597         }
598 #if defined(HAVE_LINUX_FALLOCATE)
599         return fallocate(fd, lmode, offset, len);
600 #endif
601 #else
602         /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
603         errno = ENOSYS;
604         return -1;
605 #endif
606 }
607
608 #if HAVE_KERNEL_SHARE_MODES
609 #ifndef LOCK_MAND
610 #define LOCK_MAND       32      /* This is a mandatory flock */
611 #define LOCK_READ       64      /* ... Which allows concurrent read operations */
612 #define LOCK_WRITE      128     /* ... Which allows concurrent write operations */
613 #define LOCK_RW         192     /* ... Which allows concurrent read & write ops */
614 #endif
615 #endif
616
617 /*******************************************************************
618  A flock() wrapper that will perform the kernel flock.
619 ********************************************************************/
620
621 void kernel_flock(int fd, uint32 share_mode, uint32 access_mask)
622 {
623 #if HAVE_KERNEL_SHARE_MODES
624         int kernel_mode = 0;
625         if (share_mode == FILE_SHARE_WRITE) {
626                 kernel_mode = LOCK_MAND|LOCK_WRITE;
627         } else if (share_mode == FILE_SHARE_READ) {
628                 kernel_mode = LOCK_MAND|LOCK_READ;
629         } else if (share_mode == FILE_SHARE_NONE) {
630                 kernel_mode = LOCK_MAND;
631         }
632         if (kernel_mode) {
633                 flock(fd, kernel_mode);
634         }
635 #endif
636         ;
637 }
638
639
640
641 /*******************************************************************
642  An fdopendir wrapper.
643 ********************************************************************/
644
645 DIR *sys_fdopendir(int fd)
646 {
647 #if defined(HAVE_FDOPENDIR)
648         return fdopendir(fd);
649 #else
650         errno = ENOSYS;
651         return NULL;
652 #endif
653 }
654
655 /*******************************************************************
656  An mknod() wrapper.
657 ********************************************************************/
658
659 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
660 {
661 #if defined(HAVE_MKNOD)
662         return mknod(path, mode, dev);
663 #else
664         /* No mknod system call. */
665         errno = ENOSYS;
666         return -1;
667 #endif
668 }
669
670 /*******************************************************************
671 The wait() calls vary between systems
672 ********************************************************************/
673
674 int sys_waitpid(pid_t pid,int *status,int options)
675 {
676 #ifdef HAVE_WAITPID
677         return waitpid(pid,status,options);
678 #else /* HAVE_WAITPID */
679         return wait4(pid, status, options, NULL);
680 #endif /* HAVE_WAITPID */
681 }
682
683 /*******************************************************************
684  System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
685  on error (malloc fail usually).
686 ********************************************************************/
687
688 char *sys_getwd(void)
689 {
690 #ifdef GETCWD_TAKES_NULL
691         return getcwd(NULL, 0);
692 #elif HAVE_GETCWD
693         char *wd = NULL, *s = NULL;
694         size_t allocated = PATH_MAX;
695
696         while (1) {
697                 s = SMB_REALLOC_ARRAY(s, char, allocated);
698                 if (s == NULL) {
699                         return NULL;
700                 }
701                 wd = getcwd(s, allocated);
702                 if (wd) {
703                         break;
704                 }
705                 if (errno != ERANGE) {
706                         SAFE_FREE(s);
707                         break;
708                 }
709                 allocated *= 2;
710                 if (allocated < PATH_MAX) {
711                         SAFE_FREE(s);
712                         break;
713                 }
714         }
715         return wd;
716 #else
717         char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
718         if (s == NULL) {
719                 return NULL;
720         }
721         return getwd(s);
722 #endif
723 }
724
725 #if defined(HAVE_POSIX_CAPABILITIES)
726
727 /**************************************************************************
728  Try and abstract process capabilities (for systems that have them).
729 ****************************************************************************/
730
731 /* Set the POSIX capabilities needed for the given purpose into the effective
732  * capability set of the current process. Make sure they are always removed
733  * from the inheritable set, because there is no circumstance in which our
734  * children should inherit our elevated privileges.
735  */
736 static bool set_process_capability(enum smbd_capability capability,
737                                    bool enable)
738 {
739         cap_value_t cap_vals[2] = {0};
740         int num_cap_vals = 0;
741
742         cap_t cap;
743
744 #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
745         /* On Linux, make sure that any capabilities we grab are sticky
746          * across UID changes. We expect that this would allow us to keep both
747          * the effective and permitted capability sets, but as of circa 2.6.16,
748          * only the permitted set is kept. It is a bug (which we work around)
749          * that the effective set is lost, but we still require the effective
750          * set to be kept.
751          */
752         if (!prctl(PR_GET_KEEPCAPS)) {
753                 prctl(PR_SET_KEEPCAPS, 1);
754         }
755 #endif
756
757         cap = cap_get_proc();
758         if (cap == NULL) {
759                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
760                         strerror(errno)));
761                 return False;
762         }
763
764         switch (capability) {
765                 case KERNEL_OPLOCK_CAPABILITY:
766 #ifdef CAP_NETWORK_MGT
767                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
768                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
769 #endif
770                         break;
771                 case DMAPI_ACCESS_CAPABILITY:
772 #ifdef CAP_DEVICE_MGT
773                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
774                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
775 #elif CAP_MKNOD
776                         /* Linux has CAP_MKNOD for DMAPI access. */
777                         cap_vals[num_cap_vals++] = CAP_MKNOD;
778 #endif
779                         break;
780                 case LEASE_CAPABILITY:
781 #ifdef CAP_LEASE
782                         cap_vals[num_cap_vals++] = CAP_LEASE;
783 #endif
784                         break;
785                 case DAC_OVERRIDE_CAPABILITY:
786 #ifdef CAP_DAC_OVERRIDE
787                         cap_vals[num_cap_vals++] = CAP_DAC_OVERRIDE;
788 #endif
789         }
790
791         SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
792
793         if (num_cap_vals == 0) {
794                 cap_free(cap);
795                 return True;
796         }
797
798         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
799                 enable ? CAP_SET : CAP_CLEAR);
800
801         /* We never want to pass capabilities down to our children, so make
802          * sure they are not inherited.
803          */
804         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
805
806         if (cap_set_proc(cap) == -1) {
807                 DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
808                         strerror(errno)));
809                 cap_free(cap);
810                 return False;
811         }
812
813         cap_free(cap);
814         return True;
815 }
816
817 #endif /* HAVE_POSIX_CAPABILITIES */
818
819 /****************************************************************************
820  Gain the oplock capability from the kernel if possible.
821 ****************************************************************************/
822
823 void set_effective_capability(enum smbd_capability capability)
824 {
825 #if defined(HAVE_POSIX_CAPABILITIES)
826         set_process_capability(capability, True);
827 #endif /* HAVE_POSIX_CAPABILITIES */
828 }
829
830 void drop_effective_capability(enum smbd_capability capability)
831 {
832 #if defined(HAVE_POSIX_CAPABILITIES)
833         set_process_capability(capability, False);
834 #endif /* HAVE_POSIX_CAPABILITIES */
835 }
836
837 /**************************************************************************
838  Wrapper for random().
839 ****************************************************************************/
840
841 long sys_random(void)
842 {
843 #if defined(HAVE_RANDOM)
844         return (long)random();
845 #elif defined(HAVE_RAND)
846         return (long)rand();
847 #else
848         DEBUG(0,("Error - no random function available !\n"));
849         exit(1);
850 #endif
851 }
852
853 /**************************************************************************
854  Wrapper for srandom().
855 ****************************************************************************/
856
857 void sys_srandom(unsigned int seed)
858 {
859 #if defined(HAVE_SRANDOM)
860         srandom(seed);
861 #elif defined(HAVE_SRAND)
862         srand(seed);
863 #else
864         DEBUG(0,("Error - no srandom function available !\n"));
865         exit(1);
866 #endif
867 }
868
869 #ifndef NGROUPS_MAX
870 #define NGROUPS_MAX 32 /* Guess... */
871 #endif
872
873 /**************************************************************************
874  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
875 ****************************************************************************/
876
877 int groups_max(void)
878 {
879 #if defined(SYSCONF_SC_NGROUPS_MAX)
880         int ret = sysconf(_SC_NGROUPS_MAX);
881         return (ret == -1) ? NGROUPS_MAX : ret;
882 #else
883         return NGROUPS_MAX;
884 #endif
885 }
886
887 /**************************************************************************
888  Wrap setgroups and getgroups for systems that declare getgroups() as
889  returning an array of gid_t, but actuall return an array of int.
890 ****************************************************************************/
891
892 #if defined(HAVE_BROKEN_GETGROUPS)
893
894 #ifdef HAVE_BROKEN_GETGROUPS
895 #define GID_T int
896 #else
897 #define GID_T gid_t
898 #endif
899
900 static int sys_broken_getgroups(int setlen, gid_t *gidset)
901 {
902         GID_T gid;
903         GID_T *group_list;
904         int i, ngroups;
905
906         if(setlen == 0) {
907                 return getgroups(setlen, &gid);
908         }
909
910         /*
911          * Broken case. We need to allocate a
912          * GID_T array of size setlen.
913          */
914
915         if(setlen < 0) {
916                 errno = EINVAL; 
917                 return -1;
918         } 
919
920         if (setlen == 0)
921                 setlen = groups_max();
922
923         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
924                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
925                 return -1;
926         }
927
928         if((ngroups = getgroups(setlen, group_list)) < 0) {
929                 int saved_errno = errno;
930                 SAFE_FREE(group_list);
931                 errno = saved_errno;
932                 return -1;
933         }
934
935         for(i = 0; i < ngroups; i++)
936                 gidset[i] = (gid_t)group_list[i];
937
938         SAFE_FREE(group_list);
939         return ngroups;
940 }
941
942 static int sys_broken_setgroups(int setlen, gid_t *gidset)
943 {
944         GID_T *group_list;
945         int i ; 
946
947         if (setlen == 0)
948                 return 0 ;
949
950         if (setlen < 0 || setlen > groups_max()) {
951                 errno = EINVAL; 
952                 return -1;   
953         }
954
955         /*
956          * Broken case. We need to allocate a
957          * GID_T array of size setlen.
958          */
959
960         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
961                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
962                 return -1;    
963         }
964
965         for(i = 0; i < setlen; i++) 
966                 group_list[i] = (GID_T) gidset[i]; 
967
968         if(samba_setgroups(setlen, group_list) != 0) {
969                 int saved_errno = errno;
970                 SAFE_FREE(group_list);
971                 errno = saved_errno;
972                 return -1;
973         }
974
975         SAFE_FREE(group_list);
976         return 0 ;
977 }
978
979 #endif /* HAVE_BROKEN_GETGROUPS */
980
981 /* This is a list of systems that require the first GID passed to setgroups(2)
982  * to be the effective GID. If your system is one of these, add it here.
983  */
984 #if defined (FREEBSD) || defined (DARWINOS)
985 #define USE_BSD_SETGROUPS
986 #endif
987
988 #if defined(USE_BSD_SETGROUPS)
989 /* Depending on the particular BSD implementation, the first GID that is
990  * passed to setgroups(2) will either be ignored or will set the credential's
991  * effective GID. In either case, the right thing to do is to guarantee that
992  * gidset[0] is the effective GID.
993  */
994 static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
995 {
996         gid_t *new_gidset = NULL;
997         int max;
998         int ret;
999
1000         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
1001         max = groups_max();
1002
1003         /* No group list, just make sure we are setting the efective GID. */
1004         if (setlen == 0) {
1005                 return samba_setgroups(1, &primary_gid);
1006         }
1007
1008         /* If the primary gid is not the first array element, grow the array
1009          * and insert it at the front.
1010          */
1011         if (gidset[0] != primary_gid) {
1012                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
1013                 if (new_gidset == NULL) {
1014                         return -1;
1015                 }
1016
1017                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
1018                 new_gidset[0] = primary_gid;
1019                 setlen++;
1020         }
1021
1022         if (setlen > max) {
1023                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
1024                         setlen, max));
1025                 setlen = max;
1026         }
1027
1028 #if defined(HAVE_BROKEN_GETGROUPS)
1029         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
1030 #else
1031         ret = samba_setgroups(setlen, new_gidset ? new_gidset : gidset);
1032 #endif
1033
1034         if (new_gidset) {
1035                 int errsav = errno;
1036                 SAFE_FREE(new_gidset);
1037                 errno = errsav;
1038         }
1039
1040         return ret;
1041 }
1042
1043 #endif /* USE_BSD_SETGROUPS */
1044
1045 /**************************************************************************
1046  Wrapper for getgroups. Deals with broken (int) case.
1047 ****************************************************************************/
1048
1049 int sys_getgroups(int setlen, gid_t *gidset)
1050 {
1051 #if defined(HAVE_BROKEN_GETGROUPS)
1052         return sys_broken_getgroups(setlen, gidset);
1053 #else
1054         return getgroups(setlen, gidset);
1055 #endif
1056 }
1057
1058 /**************************************************************************
1059  Wrapper for setgroups. Deals with broken (int) case and BSD case.
1060 ****************************************************************************/
1061
1062 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
1063 {
1064 #if !defined(HAVE_SETGROUPS)
1065         errno = ENOSYS;
1066         return -1;
1067 #endif /* HAVE_SETGROUPS */
1068
1069 #if defined(USE_BSD_SETGROUPS)
1070         return sys_bsd_setgroups(primary_gid, setlen, gidset);
1071 #elif defined(HAVE_BROKEN_GETGROUPS)
1072         return sys_broken_setgroups(setlen, gidset);
1073 #else
1074         return samba_setgroups(setlen, gidset);
1075 #endif
1076 }
1077
1078 /**************************************************************************
1079  Extract a command into an arg list.
1080 ****************************************************************************/
1081
1082 static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
1083 {
1084         char *trunc_cmd;
1085         char *saveptr;
1086         char *ptr;
1087         int argcl;
1088         char **argl = NULL;
1089         int i;
1090
1091         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1092                 DEBUG(0, ("talloc failed\n"));
1093                 goto nomem;
1094         }
1095
1096         if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
1097                 TALLOC_FREE(trunc_cmd);
1098                 errno = EINVAL;
1099                 return NULL;
1100         }
1101
1102         /*
1103          * Count the args.
1104          */
1105
1106         for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
1107                 argcl++;
1108
1109         TALLOC_FREE(trunc_cmd);
1110
1111         if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
1112                 goto nomem;
1113         }
1114
1115         /*
1116          * Now do the extraction.
1117          */
1118
1119         if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
1120                 goto nomem;
1121         }
1122
1123         ptr = strtok_r(trunc_cmd, " \t", &saveptr);
1124         i = 0;
1125
1126         if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1127                 goto nomem;
1128         }
1129
1130         while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
1131
1132                 if (!(argl[i++] = talloc_strdup(argl, ptr))) {
1133                         goto nomem;
1134                 }
1135         }
1136
1137         argl[i++] = NULL;
1138         TALLOC_FREE(trunc_cmd);
1139         return argl;
1140
1141  nomem:
1142         DEBUG(0, ("talloc failed\n"));
1143         TALLOC_FREE(trunc_cmd);
1144         TALLOC_FREE(argl);
1145         errno = ENOMEM;
1146         return NULL;
1147 }
1148
1149 /**************************************************************************
1150  Wrapper for popen. Safer as it doesn't search a path.
1151  Modified from the glibc sources.
1152  modified by tridge to return a file descriptor. We must kick our FILE* habit
1153 ****************************************************************************/
1154
1155 typedef struct _popen_list
1156 {
1157         int fd;
1158         pid_t child_pid;
1159         struct _popen_list *next;
1160 } popen_list;
1161
1162 static popen_list *popen_chain;
1163
1164 int sys_popen(const char *command)
1165 {
1166         int parent_end, child_end;
1167         int pipe_fds[2];
1168         popen_list *entry = NULL;
1169         char **argl = NULL;
1170         int ret;
1171
1172         if (!*command) {
1173                 errno = EINVAL;
1174                 return -1;
1175         }
1176
1177         ret = pipe(pipe_fds);
1178         if (ret < 0) {
1179                 DEBUG(0, ("sys_popen: error opening pipe: %s\n",
1180                           strerror(errno)));
1181                 return -1;
1182         }
1183
1184         parent_end = pipe_fds[0];
1185         child_end = pipe_fds[1];
1186
1187         entry = SMB_MALLOC_P(popen_list);
1188         if (entry == NULL) {
1189                 DEBUG(0, ("sys_popen: malloc failed\n"));
1190                 goto err_exit;
1191         }
1192
1193         ZERO_STRUCTP(entry);
1194
1195         /*
1196          * Extract the command and args into a NULL terminated array.
1197          */
1198
1199         argl = extract_args(NULL, command);
1200         if (argl == NULL) {
1201                 DEBUG(0, ("sys_popen: extract_args() failed: %s\n", strerror(errno)));
1202                 goto err_exit;
1203         }
1204
1205         entry->child_pid = fork();
1206
1207         if (entry->child_pid == -1) {
1208                 DEBUG(0, ("sys_popen: fork failed: %s\n", strerror(errno)));
1209                 goto err_exit;
1210         }
1211
1212         if (entry->child_pid == 0) {
1213
1214                 /*
1215                  * Child !
1216                  */
1217
1218                 int child_std_end = STDOUT_FILENO;
1219                 popen_list *p;
1220
1221                 close(parent_end);
1222                 if (child_end != child_std_end) {
1223                         dup2 (child_end, child_std_end);
1224                         close (child_end);
1225                 }
1226
1227                 /*
1228                  * POSIX.2:  "popen() shall ensure that any streams from previous
1229                  * popen() calls that remain open in the parent process are closed
1230                  * in the new child process."
1231                  */
1232
1233                 for (p = popen_chain; p; p = p->next)
1234                         close(p->fd);
1235
1236                 ret = execv(argl[0], argl);
1237                 if (ret == -1) {
1238                         DEBUG(0, ("sys_popen: ERROR executing command "
1239                                   "'%s': %s\n", command, strerror(errno)));
1240                 }
1241                 _exit (127);
1242         }
1243
1244         /*
1245          * Parent.
1246          */
1247
1248         close (child_end);
1249         TALLOC_FREE(argl);
1250
1251         /* Link into popen_chain. */
1252         entry->next = popen_chain;
1253         popen_chain = entry;
1254         entry->fd = parent_end;
1255
1256         return entry->fd;
1257
1258 err_exit:
1259
1260         SAFE_FREE(entry);
1261         TALLOC_FREE(argl);
1262         close(pipe_fds[0]);
1263         close(pipe_fds[1]);
1264         return -1;
1265 }
1266
1267 /**************************************************************************
1268  Wrapper for pclose. Modified from the glibc sources.
1269 ****************************************************************************/
1270
1271 int sys_pclose(int fd)
1272 {
1273         int wstatus;
1274         popen_list **ptr = &popen_chain;
1275         popen_list *entry = NULL;
1276         pid_t wait_pid;
1277         int status = -1;
1278
1279         /* Unlink from popen_chain. */
1280         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1281                 if ((*ptr)->fd == fd) {
1282                         entry = *ptr;
1283                         *ptr = (*ptr)->next;
1284                         status = 0;
1285                         break;
1286                 }
1287         }
1288
1289         if (status < 0 || close(entry->fd) < 0)
1290                 return -1;
1291
1292         /*
1293          * As Samba is catching and eating child process
1294          * exits we don't really care about the child exit
1295          * code, a -1 with errno = ECHILD will do fine for us.
1296          */
1297
1298         do {
1299                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1300         } while (wait_pid == -1 && errno == EINTR);
1301
1302         SAFE_FREE(entry);
1303
1304         if (wait_pid == -1)
1305                 return -1;
1306         return wstatus;
1307 }
1308
1309 /****************************************************************************
1310  Return the major devicenumber for UNIX extensions.
1311 ****************************************************************************/
1312
1313 uint32 unix_dev_major(SMB_DEV_T dev)
1314 {
1315 #if defined(HAVE_DEVICE_MAJOR_FN)
1316         return (uint32)major(dev);
1317 #else
1318         return (uint32)(dev >> 8);
1319 #endif
1320 }
1321
1322 /****************************************************************************
1323  Return the minor devicenumber for UNIX extensions.
1324 ****************************************************************************/
1325
1326 uint32 unix_dev_minor(SMB_DEV_T dev)
1327 {
1328 #if defined(HAVE_DEVICE_MINOR_FN)
1329         return (uint32)minor(dev);
1330 #else
1331         return (uint32)(dev & 0xff);
1332 #endif
1333 }
1334
1335 #if 0
1336 /*******************************************************************
1337  Return the number of CPUs.
1338 ********************************************************************/
1339
1340 int sys_get_number_of_cores(void)
1341 {
1342         int ret = -1;
1343
1344 #if defined(HAVE_SYSCONF)
1345 #if defined(_SC_NPROCESSORS_ONLN)
1346         ret = (int)sysconf(_SC_NPROCESSORS_ONLN);
1347 #endif
1348 #if defined(_SC_NPROCESSORS_CONF)
1349         if (ret < 1) {
1350                 ret = (int)sysconf(_SC_NPROCESSORS_CONF);
1351         }
1352 #endif
1353 #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
1354         int name[2];
1355         unsigned int len = sizeof(ret);
1356
1357         name[0] = CTL_HW;
1358 #if defined(HW_AVAILCPU)
1359         name[1] = HW_AVAILCPU;
1360
1361         if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
1362                 ret = -1;
1363         }
1364 #endif
1365 #if defined(HW_NCPU)
1366         if(ret < 1) {
1367                 name[0] = CTL_HW;
1368                 name[1] = HW_NCPU;
1369                 if (sysctl(nm, 2, &count, &len, NULL, 0) == -1) {
1370                         ret = -1;
1371                 }
1372         }
1373 #endif
1374 #endif
1375         if (ret < 1) {
1376                 ret = 1;
1377         }
1378         return ret;
1379 }
1380 #endif