LCOV - code coverage report
Current view: top level - source3/lib - system.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 211 239 88.3 %
Date: 2024-04-13 12:30:31 Functions: 32 36 88.9 %

          Line data    Source code
       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             : #include "lib/util/time.h"
      30             : 
      31             : #ifdef HAVE_SYS_SYSCTL_H
      32             : #include <sys/sysctl.h>
      33             : #endif
      34             : 
      35             : #ifdef HAVE_SYS_PRCTL_H
      36             : #include <sys/prctl.h>
      37             : #endif
      38             : 
      39             : /*
      40             :    The idea is that this file will eventually have wrappers around all
      41             :    important system calls in samba. The aims are:
      42             : 
      43             :    - to enable easier porting by putting OS dependent stuff in here
      44             : 
      45             :    - to allow for hooks into other "pseudo-filesystems"
      46             : 
      47             :    - to allow easier integration of things like the japanese extensions
      48             : 
      49             :    - to support the philosophy of Samba to expose the features of
      50             :      the OS within the SMB model. In general whatever file/printer/variable
      51             :      expansions/etc make sense to the OS should be acceptable to Samba.
      52             : */
      53             : 
      54             : /*******************************************************************
      55             : A send wrapper that will deal with EINTR or EAGAIN or EWOULDBLOCK.
      56             : ********************************************************************/
      57             : 
      58           0 : ssize_t sys_send(int s, const void *msg, size_t len, int flags)
      59             : {
      60           0 :         ssize_t ret;
      61             : 
      62           0 :         do {
      63           0 :                 ret = send(s, msg, len, flags);
      64           0 :         } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
      65             : 
      66           0 :         return ret;
      67             : }
      68             : 
      69             : /*******************************************************************
      70             : A recvfrom wrapper that will deal with EINTR.
      71             : NB. As used with non-blocking sockets, return on EAGAIN/EWOULDBLOCK
      72             : ********************************************************************/
      73             : 
      74        9379 : ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
      75             : {
      76           0 :         ssize_t ret;
      77             : 
      78           0 :         do {
      79        9379 :                 ret = recvfrom(s, buf, len, flags, from, fromlen);
      80        9379 :         } while (ret == -1 && (errno == EINTR));
      81        9379 :         return ret;
      82             : }
      83             : 
      84             : /*******************************************************************
      85             : A fcntl wrapper that will deal with EINTR.
      86             : ********************************************************************/
      87             : 
      88      205779 : int sys_fcntl_ptr(int fd, int cmd, void *arg)
      89             : {
      90         113 :         int ret;
      91             : 
      92         113 :         do {
      93      205779 :                 ret = fcntl(fd, cmd, arg);
      94      205779 :         } while (ret == -1 && errno == EINTR);
      95      205779 :         return ret;
      96             : }
      97             : 
      98             : /*******************************************************************
      99             : A fcntl wrapper that will deal with EINTR.
     100             : ********************************************************************/
     101             : 
     102           0 : int sys_fcntl_long(int fd, int cmd, long arg)
     103             : {
     104           0 :         int ret;
     105             : 
     106           0 :         do {
     107           0 :                 ret = fcntl(fd, cmd, arg);
     108           0 :         } while (ret == -1 && errno == EINTR);
     109           0 :         return ret;
     110             : }
     111             : 
     112             : /*******************************************************************
     113             : A fcntl wrapper that will deal with EINTR.
     114             : ********************************************************************/
     115             : 
     116      381748 : int sys_fcntl_int(int fd, int cmd, int arg)
     117             : {
     118         898 :         int ret;
     119             : 
     120         898 :         do {
     121      381748 :                 ret = fcntl(fd, cmd, arg);
     122      381748 :         } while (ret == -1 && errno == EINTR);
     123      381748 :         return ret;
     124             : }
     125             : 
     126             : /****************************************************************************
     127             :  Return the best approximation to a 'create time' under UNIX from a stat
     128             :  structure.
     129             : ****************************************************************************/
     130             : 
     131    39448346 : static struct timespec calc_create_time_stat(const struct stat *st)
     132             : {
     133      135549 :         struct timespec ret, ret1;
     134    39448346 :         struct timespec c_time = get_ctimespec(st);
     135    39448346 :         struct timespec m_time = get_mtimespec(st);
     136    39448346 :         struct timespec a_time = get_atimespec(st);
     137             : 
     138    39448346 :         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
     139    39448346 :         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
     140             : 
     141    39448346 :         if(!null_timespec(ret1)) {
     142    39446506 :                 return ret1;
     143             :         }
     144             : 
     145             :         /*
     146             :          * One of ctime, mtime or atime was zero (probably atime).
     147             :          * Just return MIN(ctime, mtime).
     148             :          */
     149        1840 :         return ret;
     150             : }
     151             : 
     152             : /****************************************************************************
     153             :  Return the best approximation to a 'create time' under UNIX from a stat_ex
     154             :  structure.
     155             : ****************************************************************************/
     156             : 
     157       16827 : static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
     158             : {
     159           5 :         struct timespec ret, ret1;
     160       16827 :         struct timespec c_time = st->st_ex_ctime;
     161       16827 :         struct timespec m_time = st->st_ex_mtime;
     162       16827 :         struct timespec a_time = st->st_ex_atime;
     163             : 
     164       16827 :         ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
     165       16827 :         ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
     166             : 
     167       16827 :         if(!null_timespec(ret1)) {
     168       16771 :                 return ret1;
     169             :         }
     170             : 
     171             :         /*
     172             :          * One of ctime, mtime or atime was zero (probably atime).
     173             :          * Just return MIN(ctime, mtime).
     174             :          */
     175          56 :         return ret;
     176             : }
     177             : 
     178             : /****************************************************************************
     179             :  Return the 'create time' from a stat struct if it exists (birthtime) or else
     180             :  use the best approximation.
     181             : ****************************************************************************/
     182             : 
     183    39447426 : static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
     184             :                                  bool fake_dir_create_times)
     185             : {
     186    39447426 :         if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
     187           0 :                 dst->st_ex_btime.tv_sec = 315493200L;          /* 1/1/1980 */
     188           0 :                 dst->st_ex_btime.tv_nsec = 0;
     189             :         }
     190             : 
     191    39447426 :         dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
     192             : 
     193             : #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
     194             :         dst->st_ex_btime = pst->st_birthtimespec;
     195             : #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
     196             :         dst->st_ex_btime.tv_sec = pst->st_birthtime;
     197             :         dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
     198             : #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
     199             :         dst->st_ex_btime.tv_sec = pst->st_birthtime;
     200             :         dst->st_ex_btime.tv_nsec = 0;
     201             : #else
     202    39447426 :         dst->st_ex_btime = calc_create_time_stat(pst);
     203    39447426 :         dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_BTIME;
     204             : #endif
     205             : 
     206             :         /* Deal with systems that don't initialize birthtime correctly.
     207             :          * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
     208             :          */
     209    39447426 :         if (null_timespec(dst->st_ex_btime)) {
     210         920 :                 dst->st_ex_btime = calc_create_time_stat(pst);
     211         920 :                 dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_BTIME;
     212             :         }
     213    39447426 : }
     214             : 
     215             : /****************************************************************************
     216             :  If we update a timestamp in a stat_ex struct we may have to recalculate
     217             :  the birthtime. For now only implement this for write time, but we may
     218             :  also need to do it for atime and ctime. JRA.
     219             : ****************************************************************************/
     220             : 
     221      373230 : void update_stat_ex_mtime(struct stat_ex *dst,
     222             :                                 struct timespec write_ts)
     223             : {
     224      373230 :         dst->st_ex_mtime = write_ts;
     225             : 
     226             :         /* We may have to recalculate btime. */
     227      373230 :         if (dst->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME) {
     228       16827 :                 dst->st_ex_btime = calc_create_time_stat_ex(dst);
     229             :         }
     230      373230 : }
     231             : 
     232     2499491 : void update_stat_ex_create_time(struct stat_ex *dst,
     233             :                                 struct timespec create_time)
     234             : {
     235     2499491 :         dst->st_ex_btime = create_time;
     236     2499491 :         dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
     237     2499491 : }
     238             : 
     239     3457200 : void update_stat_ex_from_saved_stat(struct stat_ex *dst,
     240             :                                     const struct stat_ex *src)
     241             : {
     242     3457200 :         if (!VALID_STAT(*src)) {
     243      509171 :                 return;
     244             :         }
     245             : 
     246     2939009 :         if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME)) {
     247      979707 :                 update_stat_ex_create_time(dst, src->st_ex_btime);
     248             :         }
     249             : }
     250             : 
     251    39447426 : void init_stat_ex_from_stat (struct stat_ex *dst,
     252             :                             const struct stat *src,
     253             :                             bool fake_dir_create_times)
     254             : {
     255    39447426 :         dst->st_ex_dev = src->st_dev;
     256    39447426 :         dst->st_ex_ino = src->st_ino;
     257    39447426 :         dst->st_ex_mode = src->st_mode;
     258    39447426 :         dst->st_ex_nlink = src->st_nlink;
     259    39447426 :         dst->st_ex_uid = src->st_uid;
     260    39447426 :         dst->st_ex_gid = src->st_gid;
     261    39447426 :         dst->st_ex_rdev = src->st_rdev;
     262    39447426 :         dst->st_ex_size = src->st_size;
     263    39447426 :         dst->st_ex_atime = get_atimespec(src);
     264    39447426 :         dst->st_ex_mtime = get_mtimespec(src);
     265    39447426 :         dst->st_ex_ctime = get_ctimespec(src);
     266    39447426 :         dst->st_ex_iflags = 0;
     267    39447426 :         make_create_timespec(src, dst, fake_dir_create_times);
     268             : #ifdef HAVE_STAT_ST_BLKSIZE
     269    39447426 :         dst->st_ex_blksize = src->st_blksize;
     270             : #else
     271             :         dst->st_ex_blksize = STAT_ST_BLOCKSIZE;
     272             : #endif
     273             : 
     274             : #ifdef HAVE_STAT_ST_BLOCKS
     275    39447426 :         dst->st_ex_blocks = src->st_blocks;
     276             : #else
     277             :         dst->st_ex_blocks = src->st_size / dst->st_ex_blksize + 1;
     278             : #endif
     279             : 
     280             : #ifdef HAVE_STAT_ST_FLAGS
     281             :         dst->st_ex_flags = src->st_flags;
     282             : #else
     283    39447426 :         dst->st_ex_flags = 0;
     284             : #endif
     285    39447426 : }
     286             : 
     287             : /*******************************************************************
     288             : A stat() wrapper.
     289             : ********************************************************************/
     290             : 
     291     5679391 : int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
     292             :              bool fake_dir_create_times)
     293             : {
     294       11179 :         int ret;
     295       11179 :         struct stat statbuf;
     296     5679391 :         ret = stat(fname, &statbuf);
     297     5679391 :         if (ret == 0) {
     298             :                 /* we always want directories to appear zero size */
     299     5208628 :                 if (S_ISDIR(statbuf.st_mode)) {
     300     4877891 :                         statbuf.st_size = 0;
     301             :                 }
     302     5208628 :                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
     303             :         }
     304     5679391 :         return ret;
     305             : }
     306             : 
     307             : /*******************************************************************
     308             :  An fstat() wrapper.
     309             : ********************************************************************/
     310             : 
     311    34141472 : int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times)
     312             : {
     313      125539 :         int ret;
     314      125539 :         struct stat statbuf;
     315    34141472 :         ret = fstat(fd, &statbuf);
     316    34141472 :         if (ret == 0) {
     317             :                 /* we always want directories to appear zero size */
     318    34141264 :                 if (S_ISDIR(statbuf.st_mode)) {
     319    20469698 :                         statbuf.st_size = 0;
     320             :                 }
     321    34141264 :                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
     322             :         }
     323    34141472 :         return ret;
     324             : }
     325             : 
     326             : /*******************************************************************
     327             :  An lstat() wrapper.
     328             : ********************************************************************/
     329             : 
     330       68900 : int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf,
     331             :               bool fake_dir_create_times)
     332             : {
     333          70 :         int ret;
     334          70 :         struct stat statbuf;
     335       68900 :         ret = lstat(fname, &statbuf);
     336       68900 :         if (ret == 0) {
     337             :                 /* we always want directories to appear zero size */
     338       48331 :                 if (S_ISDIR(statbuf.st_mode)) {
     339       23888 :                         statbuf.st_size = 0;
     340             :                 }
     341       48331 :                 init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
     342             :         }
     343       68900 :         return ret;
     344             : }
     345             : 
     346             : /*******************************************************************
     347             :  An fstatat() wrapper.
     348             : ********************************************************************/
     349             : 
     350       49578 : int sys_fstatat(int fd,
     351             :                 const char *pathname,
     352             :                 SMB_STRUCT_STAT *sbuf,
     353             :                 int flags,
     354             :                 bool fake_dir_create_times)
     355             : {
     356         156 :         int ret;
     357         156 :         struct stat statbuf;
     358             : 
     359       49578 :         ret = fstatat(fd, pathname, &statbuf, flags);
     360       49578 :         if (ret != 0) {
     361         375 :                 return -1;
     362             :         }
     363             : 
     364             :         /* we always want directories to appear zero size */
     365       49203 :         if (S_ISDIR(statbuf.st_mode)) {
     366       12415 :                 statbuf.st_size = 0;
     367             :         }
     368       49203 :         init_stat_ex_from_stat(sbuf, &statbuf, fake_dir_create_times);
     369       49203 :         return 0;
     370             : }
     371             : 
     372             : /*******************************************************************
     373             :  An posix_fallocate() wrapper.
     374             : ********************************************************************/
     375           0 : int sys_posix_fallocate(int fd, off_t offset, off_t len)
     376             : {
     377             : #if defined(HAVE_POSIX_FALLOCATE)
     378           0 :         return posix_fallocate(fd, offset, len);
     379             : #elif defined(F_RESVSP64)
     380             :         /* this handles XFS on IRIX */
     381             :         struct flock64 fl;
     382             :         off_t new_len = offset + len;
     383             :         int ret;
     384             :         struct stat64 sbuf;
     385             : 
     386             :         /* unlikely to get a too large file on a 64bit system but ... */
     387             :         if (new_len < 0)
     388             :                 return EFBIG;
     389             : 
     390             :         fl.l_whence = SEEK_SET;
     391             :         fl.l_start = offset;
     392             :         fl.l_len = len;
     393             : 
     394             :         ret=fcntl(fd, F_RESVSP64, &fl);
     395             : 
     396             :         if (ret != 0)
     397             :                 return errno;
     398             : 
     399             :         /* Make sure the file gets enlarged after we allocated space: */
     400             :         fstat64(fd, &sbuf);
     401             :         if (new_len > sbuf.st_size)
     402             :                 ftruncate64(fd, new_len);
     403             :         return 0;
     404             : #else
     405             :         return ENOSYS;
     406             : #endif
     407             : }
     408             : 
     409             : /*******************************************************************
     410             :  An fallocate() function that matches the semantics of the Linux one.
     411             : ********************************************************************/
     412             : 
     413             : #ifdef HAVE_LINUX_FALLOC_H
     414             : #include <linux/falloc.h>
     415             : #endif
     416             : 
     417         186 : int sys_fallocate(int fd, uint32_t mode, off_t offset, off_t len)
     418             : {
     419             : #if defined(HAVE_LINUX_FALLOCATE)
     420         186 :         int lmode = 0;
     421             : 
     422         186 :         if (mode & VFS_FALLOCATE_FL_KEEP_SIZE) {
     423         186 :                 lmode |= FALLOC_FL_KEEP_SIZE;
     424         186 :                 mode &= ~VFS_FALLOCATE_FL_KEEP_SIZE;
     425             :         }
     426             : 
     427             : #if defined(HAVE_FALLOC_FL_PUNCH_HOLE)
     428         186 :         if (mode & VFS_FALLOCATE_FL_PUNCH_HOLE) {
     429         186 :                 lmode |= FALLOC_FL_PUNCH_HOLE;
     430         186 :                 mode &= ~VFS_FALLOCATE_FL_PUNCH_HOLE;
     431             :         }
     432             : #endif  /* HAVE_FALLOC_FL_PUNCH_HOLE */
     433             : 
     434         186 :         if (mode != 0) {
     435           0 :                 DEBUG(2, ("unmapped fallocate flags: %lx\n",
     436             :                       (unsigned long)mode));
     437           0 :                 errno = EINVAL;
     438           0 :                 return -1;
     439             :         }
     440         186 :         return fallocate(fd, lmode, offset, len);
     441             : #else   /* HAVE_LINUX_FALLOCATE */
     442             :         /* TODO - plumb in fallocate from other filesysetms like VXFS etc. JRA. */
     443             :         errno = ENOSYS;
     444             :         return -1;
     445             : #endif  /* HAVE_LINUX_FALLOCATE */
     446             : }
     447             : 
     448             : /*******************************************************************
     449             :  An fdopendir wrapper.
     450             : ********************************************************************/
     451             : 
     452      306964 : DIR *sys_fdopendir(int fd)
     453             : {
     454             : #if defined(HAVE_FDOPENDIR)
     455      306964 :         return fdopendir(fd);
     456             : #else
     457             :         errno = ENOSYS;
     458             :         return NULL;
     459             : #endif
     460             : }
     461             : 
     462             : /*******************************************************************
     463             :  An mknod() wrapper.
     464             : ********************************************************************/
     465             : 
     466           0 : int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
     467             : {
     468             : #if defined(HAVE_MKNOD)
     469           0 :         return mknod(path, mode, dev);
     470             : #else
     471             :         /* No mknod system call. */
     472             :         errno = ENOSYS;
     473             :         return -1;
     474             : #endif
     475             : }
     476             : 
     477             : /*******************************************************************
     478             :  A mknodat() wrapper.
     479             : ********************************************************************/
     480             : 
     481           2 : int sys_mknodat(int dirfd, const char *path, mode_t mode, SMB_DEV_T dev)
     482             : {
     483             : #if defined(HAVE_MKNODAT)
     484           2 :         return mknodat(dirfd, path, mode, dev);
     485             : #else
     486             :         /* No mknod system call. */
     487             :         errno = ENOSYS;
     488             :         return -1;
     489             : #endif
     490             : }
     491             : 
     492             : /*******************************************************************
     493             :  System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
     494             :  on error (malloc fail usually).
     495             : ********************************************************************/
     496             : 
     497      102328 : char *sys_getwd(void)
     498             : {
     499             : #ifdef GETCWD_TAKES_NULL
     500      102328 :         return getcwd(NULL, 0);
     501             : #elif defined(HAVE_GETCWD)
     502             :         char *wd = NULL, *s = NULL;
     503             :         size_t allocated = PATH_MAX;
     504             : 
     505             :         while (1) {
     506             :                 s = SMB_REALLOC_ARRAY(s, char, allocated);
     507             :                 if (s == NULL) {
     508             :                         return NULL;
     509             :                 }
     510             :                 wd = getcwd(s, allocated);
     511             :                 if (wd) {
     512             :                         break;
     513             :                 }
     514             :                 if (errno != ERANGE) {
     515             :                         int saved_errno = errno;
     516             :                         SAFE_FREE(s);
     517             :                         errno = saved_errno;
     518             :                         break;
     519             :                 }
     520             :                 allocated *= 2;
     521             :                 if (allocated < PATH_MAX) {
     522             :                         SAFE_FREE(s);
     523             :                         break;
     524             :                 }
     525             :         }
     526             :         return wd;
     527             : #else
     528             :         char *wd = NULL;
     529             :         char *s = SMB_MALLOC_ARRAY(char, PATH_MAX);
     530             :         if (s == NULL) {
     531             :                 return NULL;
     532             :         }
     533             :         wd = getwd(s);
     534             :         if (wd == NULL) {
     535             :                 int saved_errno = errno;
     536             :                 SAFE_FREE(s);
     537             :                 errno = saved_errno;
     538             :         }
     539             :         return wd;
     540             : #endif
     541             : }
     542             : 
     543             : #if defined(HAVE_POSIX_CAPABILITIES)
     544             : 
     545             : /**************************************************************************
     546             :  Try and abstract process capabilities (for systems that have them).
     547             : ****************************************************************************/
     548             : 
     549             : /* Set the POSIX capabilities needed for the given purpose into the effective
     550             :  * capability set of the current process. Make sure they are always removed
     551             :  * from the inheritable set, because there is no circumstance in which our
     552             :  * children should inherit our elevated privileges.
     553             :  */
     554        7198 : static bool set_process_capability(enum smbd_capability capability,
     555             :                                    bool enable)
     556             : {
     557             :         /* "5" is the number of "num_cap_vals++" below */
     558        7198 :         cap_value_t cap_vals[5] = {0};
     559        7198 :         size_t num_cap_vals = 0;
     560             : 
     561           5 :         cap_t cap;
     562             : 
     563             : #if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
     564             :         /* On Linux, make sure that any capabilities we grab are sticky
     565             :          * across UID changes. We expect that this would allow us to keep both
     566             :          * the effective and permitted capability sets, but as of circa 2.6.16,
     567             :          * only the permitted set is kept. It is a bug (which we work around)
     568             :          * that the effective set is lost, but we still require the effective
     569             :          * set to be kept.
     570             :          */
     571        7198 :         if (!prctl(PR_GET_KEEPCAPS)) {
     572         916 :                 prctl(PR_SET_KEEPCAPS, 1);
     573             :         }
     574             : #endif
     575             : 
     576        7198 :         cap = cap_get_proc();
     577        7198 :         if (cap == NULL) {
     578           0 :                 DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
     579             :                         strerror(errno)));
     580           0 :                 return False;
     581             :         }
     582             : 
     583        7198 :         switch (capability) {
     584             :                 /*
     585             :                  * WARNING: If you add any #ifdef for a fresh
     586             :                  * capability, bump up the array size in the
     587             :                  * declaration of cap_vals[] above just to be
     588             :                  * trivially safe to never overwrite cap_vals[].
     589             :                  */
     590        3150 :                 case KERNEL_OPLOCK_CAPABILITY:
     591             : #ifdef CAP_NETWORK_MGT
     592             :                         /* IRIX has CAP_NETWORK_MGT for oplocks. */
     593             :                         cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
     594             : #endif
     595        3150 :                         break;
     596        3150 :                 case DMAPI_ACCESS_CAPABILITY:
     597             : #ifdef CAP_DEVICE_MGT
     598             :                         /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
     599             :                         cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
     600             : #elif CAP_MKNOD
     601             :                         /* Linux has CAP_MKNOD for DMAPI access. */
     602        3150 :                         cap_vals[num_cap_vals++] = CAP_MKNOD;
     603             : #endif
     604        3150 :                         break;
     605           0 :                 case LEASE_CAPABILITY:
     606             : #ifdef CAP_LEASE
     607           0 :                         cap_vals[num_cap_vals++] = CAP_LEASE;
     608             : #endif
     609           0 :                         break;
     610         898 :                 case DAC_OVERRIDE_CAPABILITY:
     611             : #ifdef CAP_DAC_OVERRIDE
     612         898 :                         cap_vals[num_cap_vals++] = CAP_DAC_OVERRIDE;
     613             : #endif
     614             :         }
     615             : 
     616        7198 :         if (num_cap_vals == 0) {
     617        3150 :                 cap_free(cap);
     618        3150 :                 return True;
     619             :         }
     620             : 
     621        4048 :         cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
     622             :                 enable ? CAP_SET : CAP_CLEAR);
     623             : 
     624             :         /* We never want to pass capabilities down to our children, so make
     625             :          * sure they are not inherited.
     626             :          */
     627        4048 :         cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
     628             : 
     629        4048 :         if (cap_set_proc(cap) == -1) {
     630         898 :                 DBG_ERR("adding capability %d: cap_set_proc failed: %s\n",
     631             :                         capability, strerror(errno));
     632         898 :                 cap_free(cap);
     633         898 :                 return False;
     634             :         }
     635        3150 :         DBG_INFO("added capability %d\n", capability);
     636             : 
     637        3150 :         cap_free(cap);
     638        3150 :         return True;
     639             : }
     640             : 
     641             : #endif /* HAVE_POSIX_CAPABILITIES */
     642             : 
     643             : /****************************************************************************
     644             :  Gain the oplock capability from the kernel if possible.
     645             : ****************************************************************************/
     646             : 
     647             : #if defined(HAVE_POSIX_CAPABILITIES) && defined(CAP_DAC_OVERRIDE)
     648             : static bool have_cap_dac_override = true;
     649             : #else
     650             : static bool have_cap_dac_override = false;
     651             : #endif
     652             : 
     653     1493419 : void set_effective_capability(enum smbd_capability capability)
     654             : {
     655     1493419 :         bool ret = false;
     656             : 
     657     1493419 :         if (capability != DAC_OVERRIDE_CAPABILITY || have_cap_dac_override) {
     658             : #if defined(HAVE_POSIX_CAPABILITIES)
     659         898 :                 ret = set_process_capability(capability, True);
     660             : #endif /* HAVE_POSIX_CAPABILITIES */
     661             :         }
     662             : 
     663             :         /*
     664             :          * Fallback to become_root() if CAP_DAC_OVERRIDE is not
     665             :          * available.
     666             :          */
     667     1493419 :         if (capability == DAC_OVERRIDE_CAPABILITY) {
     668     1493419 :                 if (!ret) {
     669     1493419 :                         have_cap_dac_override = false;
     670             :                 }
     671     1493419 :                 if (!have_cap_dac_override) {
     672     1493419 :                         become_root();
     673             :                 }
     674             :         }
     675     1493419 : }
     676             : 
     677     1499719 : void drop_effective_capability(enum smbd_capability capability)
     678             : {
     679     1499719 :         if (capability != DAC_OVERRIDE_CAPABILITY || have_cap_dac_override) {
     680             : #if defined(HAVE_POSIX_CAPABILITIES)
     681        6300 :                 set_process_capability(capability, False);
     682             : #endif /* HAVE_POSIX_CAPABILITIES */
     683             :         } else {
     684     1493419 :                 unbecome_root();
     685             :         }
     686     1499719 : }
     687             : 
     688             : /**************************************************************************
     689             :  Wrapper for random().
     690             : ****************************************************************************/
     691             : 
     692        1800 : long sys_random(void)
     693             : {
     694             : #if defined(HAVE_RANDOM)
     695        1800 :         return (long)random();
     696             : #elif defined(HAVE_RAND)
     697             :         return (long)rand();
     698             : #else
     699             :         DEBUG(0,("Error - no random function available !\n"));
     700             :         exit(1);
     701             : #endif
     702             : }
     703             : 
     704             : /**************************************************************************
     705             :  Wrapper for srandom().
     706             : ****************************************************************************/
     707             : 
     708          39 : void sys_srandom(unsigned int seed)
     709             : {
     710             : #if defined(HAVE_SRANDOM)
     711          39 :         srandom(seed);
     712             : #elif defined(HAVE_SRAND)
     713             :         srand(seed);
     714             : #else
     715             :         DEBUG(0,("Error - no srandom function available !\n"));
     716             :         exit(1);
     717             : #endif
     718          39 : }
     719             : 
     720             : #ifndef NGROUPS_MAX
     721             : #define NGROUPS_MAX 32 /* Guess... */
     722             : #endif
     723             : 
     724             : /**************************************************************************
     725             :  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
     726             : ****************************************************************************/
     727             : 
     728       46313 : int setgroups_max(void)
     729             : {
     730             : #if defined(SYSCONF_SC_NGROUPS_MAX)
     731       46313 :         int ret = sysconf(_SC_NGROUPS_MAX);
     732       46313 :         return (ret == -1) ? NGROUPS_MAX : ret;
     733             : #else
     734             :         return NGROUPS_MAX;
     735             : #endif
     736             : }
     737             : 
     738       46313 : int getgroups_max(void)
     739             : {
     740             : #if defined(DARWINOS)
     741             :         /*
     742             :          * On MacOS sysconf(_SC_NGROUPS_MAX) returns 16 due to MacOS's group
     743             :          * nesting. However, The initgroups() manpage states the following:
     744             :          * "Note that OS X supports group membership in an unlimited number
     745             :          * of groups. The OS X kernel uses the group list stored in the process
     746             :          * credentials only as an initial cache.  Additional group memberships
     747             :          * are determined by communication between the operating system and the
     748             :          * opendirectoryd daemon."
     749             :          */
     750             :         return INT_MAX;
     751             : #else
     752       46313 :         return setgroups_max();
     753             : #endif
     754             : }
     755             : 
     756             : /**************************************************************************
     757             :  Wrap setgroups and getgroups for systems that declare getgroups() as
     758             :  returning an array of gid_t, but actually return an array of int.
     759             : ****************************************************************************/
     760             : 
     761             : #if defined(HAVE_BROKEN_GETGROUPS)
     762             : 
     763             : #ifdef HAVE_BROKEN_GETGROUPS
     764             : #define GID_T int
     765             : #else
     766             : #define GID_T gid_t
     767             : #endif
     768             : 
     769             : static int sys_broken_getgroups(int setlen, gid_t *gidset)
     770             : {
     771             :         GID_T *group_list;
     772             :         int i, ngroups;
     773             : 
     774             :         if(setlen == 0) {
     775             :                 return getgroups(0, NULL);
     776             :         }
     777             : 
     778             :         /*
     779             :          * Broken case. We need to allocate a
     780             :          * GID_T array of size setlen.
     781             :          */
     782             : 
     783             :         if(setlen < 0) {
     784             :                 errno = EINVAL;
     785             :                 return -1;
     786             :         }
     787             : 
     788             :         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
     789             :                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
     790             :                 return -1;
     791             :         }
     792             : 
     793             :         if((ngroups = getgroups(setlen, group_list)) < 0) {
     794             :                 int saved_errno = errno;
     795             :                 SAFE_FREE(group_list);
     796             :                 errno = saved_errno;
     797             :                 return -1;
     798             :         }
     799             : 
     800             :         /*
     801             :          * We're safe here as if ngroups > setlen then
     802             :          * getgroups *must* return EINVAL.
     803             :          * pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html
     804             :          */
     805             : 
     806             :         for(i = 0; i < ngroups; i++)
     807             :                 gidset[i] = (gid_t)group_list[i];
     808             : 
     809             :         SAFE_FREE(group_list);
     810             :         return ngroups;
     811             : }
     812             : 
     813             : static int sys_broken_setgroups(int setlen, gid_t *gidset)
     814             : {
     815             :         GID_T *group_list;
     816             :         int i ;
     817             : 
     818             :         if (setlen == 0)
     819             :                 return 0 ;
     820             : 
     821             :         if (setlen < 0 || setlen > setgroups_max()) {
     822             :                 errno = EINVAL;
     823             :                 return -1;
     824             :         }
     825             : 
     826             :         /*
     827             :          * Broken case. We need to allocate a
     828             :          * GID_T array of size setlen.
     829             :          */
     830             : 
     831             :         if((group_list = SMB_MALLOC_ARRAY(GID_T, setlen)) == NULL) {
     832             :                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
     833             :                 return -1;
     834             :         }
     835             : 
     836             :         for(i = 0; i < setlen; i++)
     837             :                 group_list[i] = (GID_T) gidset[i];
     838             : 
     839             :         if(samba_setgroups(setlen, group_list) != 0) {
     840             :                 int saved_errno = errno;
     841             :                 SAFE_FREE(group_list);
     842             :                 errno = saved_errno;
     843             :                 return -1;
     844             :         }
     845             : 
     846             :         SAFE_FREE(group_list);
     847             :         return 0 ;
     848             : }
     849             : 
     850             : #endif /* HAVE_BROKEN_GETGROUPS */
     851             : 
     852             : /* This is a list of systems that require the first GID passed to setgroups(2)
     853             :  * to be the effective GID. If your system is one of these, add it here.
     854             :  */
     855             : #if defined (FREEBSD) || defined (DARWINOS)
     856             : #define USE_BSD_SETGROUPS
     857             : #endif
     858             : 
     859             : #if defined(USE_BSD_SETGROUPS)
     860             : /* Depending on the particular BSD implementation, the first GID that is
     861             :  * passed to setgroups(2) will either be ignored or will set the credential's
     862             :  * effective GID. In either case, the right thing to do is to guarantee that
     863             :  * gidset[0] is the effective GID.
     864             :  */
     865             : static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
     866             : {
     867             :         gid_t *new_gidset = NULL;
     868             :         int max;
     869             :         int ret;
     870             : 
     871             :         /* setgroups(2) will fail with EINVAL if we pass too many groups. */
     872             :         max = setgroups_max();
     873             : 
     874             :         /* No group list, just make sure we are setting the effective GID. */
     875             :         if (setlen == 0) {
     876             :                 return samba_setgroups(1, &primary_gid);
     877             :         }
     878             : 
     879             :         /* If the primary gid is not the first array element, grow the array
     880             :          * and insert it at the front.
     881             :          */
     882             :         if (gidset[0] != primary_gid) {
     883             :                 new_gidset = SMB_MALLOC_ARRAY(gid_t, setlen + 1);
     884             :                 if (new_gidset == NULL) {
     885             :                         return -1;
     886             :                 }
     887             : 
     888             :                 memcpy(new_gidset + 1, gidset, (setlen * sizeof(gid_t)));
     889             :                 new_gidset[0] = primary_gid;
     890             :                 setlen++;
     891             :         }
     892             : 
     893             :         if (setlen > max) {
     894             :                 DEBUG(3, ("forced to truncate group list from %d to %d\n",
     895             :                         setlen, max));
     896             :                 setlen = max;
     897             :         }
     898             : 
     899             : #if defined(HAVE_BROKEN_GETGROUPS)
     900             :         ret = sys_broken_setgroups(setlen, new_gidset ? new_gidset : gidset);
     901             : #else
     902             :         ret = samba_setgroups(setlen, new_gidset ? new_gidset : gidset);
     903             : #endif
     904             : 
     905             :         if (new_gidset) {
     906             :                 int errsav = errno;
     907             :                 SAFE_FREE(new_gidset);
     908             :                 errno = errsav;
     909             :         }
     910             : 
     911             :         return ret;
     912             : }
     913             : 
     914             : #endif /* USE_BSD_SETGROUPS */
     915             : 
     916             : /**************************************************************************
     917             :  Wrapper for getgroups. Deals with broken (int) case.
     918             : ****************************************************************************/
     919             : 
     920     7599267 : int sys_getgroups(int setlen, gid_t *gidset)
     921             : {
     922             : #if defined(HAVE_BROKEN_GETGROUPS)
     923             :         return sys_broken_getgroups(setlen, gidset);
     924             : #else
     925     7599267 :         return getgroups(setlen, gidset);
     926             : #endif
     927             : }
     928             : 
     929             : /**************************************************************************
     930             :  Wrapper for setgroups. Deals with broken (int) case and BSD case.
     931             : ****************************************************************************/
     932             : 
     933     9877772 : int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
     934             : {
     935             : #if !defined(HAVE_SETGROUPS)
     936             :         errno = ENOSYS;
     937             :         return -1;
     938             : #endif /* HAVE_SETGROUPS */
     939             : 
     940             : #if defined(USE_BSD_SETGROUPS)
     941             :         return sys_bsd_setgroups(primary_gid, setlen, gidset);
     942             : #elif defined(HAVE_BROKEN_GETGROUPS)
     943             :         return sys_broken_setgroups(setlen, gidset);
     944             : #else
     945     9877772 :         return samba_setgroups(setlen, gidset);
     946             : #endif
     947             : }
     948             : 
     949             : /****************************************************************************
     950             :  Return the major devicenumber for UNIX extensions.
     951             : ****************************************************************************/
     952             : 
     953         576 : uint32_t unix_dev_major(SMB_DEV_T dev)
     954             : {
     955             : #if defined(HAVE_DEVICE_MAJOR_FN)
     956         576 :         return (uint32_t)major(dev);
     957             : #else
     958             :         return (uint32_t)(dev >> 8);
     959             : #endif
     960             : }
     961             : 
     962             : /****************************************************************************
     963             :  Return the minor devicenumber for UNIX extensions.
     964             : ****************************************************************************/
     965             : 
     966         576 : uint32_t unix_dev_minor(SMB_DEV_T dev)
     967             : {
     968             : #if defined(HAVE_DEVICE_MINOR_FN)
     969         576 :         return (uint32_t)minor(dev);
     970             : #else
     971             :         return (uint32_t)(dev & 0xff);
     972             : #endif
     973             : }
     974             : 
     975             : /**************************************************************************
     976             :  Wrapper for realpath.
     977             : ****************************************************************************/
     978             : 
     979     3524302 : char *sys_realpath(const char *path)
     980             : {
     981       12206 :         char *result;
     982             : 
     983             : #ifdef REALPATH_TAKES_NULL
     984     3524302 :         result = realpath(path, NULL);
     985             : #else
     986             :         result = SMB_MALLOC_ARRAY(char, PATH_MAX + 1);
     987             :         if (result) {
     988             :                 char *resolved_path = realpath(path, result);
     989             :                 if (!resolved_path) {
     990             :                         SAFE_FREE(result);
     991             :                 } else {
     992             :                         /* SMB_ASSERT(result == resolved_path) ? */
     993             :                         result = resolved_path;
     994             :                 }
     995             :         }
     996             : #endif
     997     3524302 :         return result;
     998             : }
     999             : 
    1000             : #if 0
    1001             : /*******************************************************************
    1002             :  Return the number of CPUs.
    1003             : ********************************************************************/
    1004             : 
    1005             : int sys_get_number_of_cores(void)
    1006             : {
    1007             :         int ret = -1;
    1008             : 
    1009             : #if defined(HAVE_SYSCONF)
    1010             : #if defined(_SC_NPROCESSORS_ONLN)
    1011             :         ret = (int)sysconf(_SC_NPROCESSORS_ONLN);
    1012             : #endif
    1013             : #if defined(_SC_NPROCESSORS_CONF)
    1014             :         if (ret < 1) {
    1015             :                 ret = (int)sysconf(_SC_NPROCESSORS_CONF);
    1016             :         }
    1017             : #endif
    1018             : #elif defined(HAVE_SYSCTL) && defined(CTL_HW)
    1019             :         int name[2];
    1020             :         unsigned int len = sizeof(ret);
    1021             : 
    1022             :         name[0] = CTL_HW;
    1023             : #if defined(HW_AVAILCPU)
    1024             :         name[1] = HW_AVAILCPU;
    1025             : 
    1026             :         if (sysctl(name, 2, &ret, &len, NULL, 0) == -1) {
    1027             :                 ret = -1;
    1028             :         }
    1029             : #endif
    1030             : #if defined(HW_NCPU)
    1031             :         if(ret < 1) {
    1032             :                 name[0] = CTL_HW;
    1033             :                 name[1] = HW_NCPU;
    1034             :                 if (sysctl(nm, 2, &count, &len, NULL, 0) == -1) {
    1035             :                         ret = -1;
    1036             :                 }
    1037             :         }
    1038             : #endif
    1039             : #endif
    1040             :         if (ret < 1) {
    1041             :                 ret = 1;
    1042             :         }
    1043             :         return ret;
    1044             : }
    1045             : #endif
    1046             : 
    1047      323261 : bool sys_have_proc_fds(void)
    1048             : {
    1049        1273 :         static bool checked = false;
    1050        1273 :         static bool have_proc_fds = false;
    1051        1273 :         struct stat sb;
    1052        1273 :         int ret;
    1053             : 
    1054      323261 :         if (checked) {
    1055      294350 :                 return have_proc_fds;
    1056             :         }
    1057             : 
    1058       28911 :         ret = stat("/proc/self/fd/0", &sb);
    1059       28911 :         have_proc_fds = (ret == 0);
    1060       28911 :         checked = true;
    1061             : 
    1062       28911 :         return have_proc_fds;
    1063             : }
    1064             : 
    1065      266775 : char *sys_proc_fd_path(int fd, struct sys_proc_fd_path_buf *buf)
    1066             : {
    1067         399 :         int written =
    1068      266775 :                 snprintf(buf->buf, sizeof(buf->buf), "/proc/self/fd/%d", fd);
    1069             : 
    1070      266775 :         SMB_ASSERT(sys_have_proc_fds() && (written >= 0));
    1071             : 
    1072      266775 :         return buf->buf;
    1073             : }

Generated by: LCOV version 1.14