source: trunk/base/src/darwintracelib1.0/readdir.c @ 136621

Last change on this file since 136621 was 117962, checked in by cal@…, 6 years ago

darwintrace: don't export symbols

  • Property svn:eol-style set to native
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2005 Apple Inc. All rights reserved.
3 * Copyright (c) 2005-2006 Paul Guyot <pguyot@kallisys.net>,
4 * All rights reserved.
5 * Copyright (c) 2006-2013 The MacPorts Project
6 *
7 * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal@macports.org $
8 *
9 * @APPLE_BSD_LICENSE_HEADER_START@
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1.  Redistributions of source code must retain the above copyright
16 *     notice, this list of conditions and the following disclaimer.
17 * 2.  Redistributions in binary form must reproduce the above copyright
18 *     notice, this list of conditions and the following disclaimer in the
19 *     documentation and/or other materials provided with the distribution.
20 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
21 *     its contributors may be used to endorse or promote products derived
22 *     from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
25 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
28 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * @APPLE_BSD_LICENSE_HEADER_END@
36 */
37
38#include "darwintrace.h"
39
40#include <errno.h>
41#include <sys/dirent.h>
42#include <sys/param.h>
43#include <sys/syscall.h>
44#include <unistd.h>
45#include <fcntl.h>
46#include <string.h>
47
48/**
49 * re-implementation of getdirent(2) and __getdirent64(2) preventing paths
50 * outside the sandbox to show up when reading the contents of a directory.
51 * Unfortunately, since we need to access the contents of the buffer, but the
52 * contents differ by architecture, we can not rely on the dirent structure
53 * defined by the header included by this program, because we don't know
54 * whether darwintrace.dylib has been compiled for 64bit or 32bit inodes. We
55 * thus copy both structs and decide at runtime.
56 */
57
58#if defined(__DARWIN_64_BIT_INO_T) && defined(HAVE___GETDIRENTRIES64)
59
60struct dirent64  {
61        __uint64_t  d_ino;      /* file number of entry */
62        __uint64_t  d_seekoff;  /* seek offset */
63        __uint16_t  d_reclen;   /* length of this record */
64        __uint16_t  d_namlen;   /* length of string in d_name */
65        __uint8_t   d_type;     /* file type */
66        char      d_name[__DARWIN_MAXPATHLEN]; /* entry name (up to MAXPATHLEN bytes) */
67};
68
69static size_t _dt_getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep) {
70#define __getdirentries64(w,x,y,z) syscall(SYS_getdirentries64, (w), (x), (y), (z))
71        __darwintrace_setup();
72
73        size_t sz = __getdirentries64(fd, buf, bufsize, basep);
74        char dirname[MAXPATHLEN];
75        size_t dnamelen;
76
77        if (-1 == fcntl(fd, F_GETPATH, dirname)) {
78                errno = EBADF;
79                return -1;
80        }
81
82        dnamelen = strlen(dirname);
83        if (dirname[dnamelen - 1] != '/') {
84                dirname[dnamelen] = '/';
85                dirname[dnamelen + 1] = '\0';
86                dnamelen++;
87        }
88
89        dnamelen = strlen(dirname);
90        size_t offset;
91        for (offset = 0; offset < sz;) {
92                struct dirent64 *dent = (struct dirent64 *)(((char *) buf) + offset);
93                dirname[dnamelen] = '\0';
94                strcat(dirname, dent->d_name);
95                if (!__darwintrace_is_in_sandbox(dirname, DT_ALLOWDIR)) {
96                        debug_printf("__getdirentries64: filtered %s\n", dirname);
97                        dent->d_ino = 0;
98                } else {
99                        debug_printf("__getdirentries64:  allowed %s\n", dirname);
100                }
101                offset += dent->d_reclen;
102        }
103
104        return sz;
105#undef __getdirentries64
106}
107
108// __getdirentries64(2) is private API. There's no header for it.
109size_t __getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep);
110DARWINTRACE_INTERPOSE(_dt_getdirentries64, __getdirentries64);
111
112#endif /* defined(__DARWIN_64_BIT_INO_T) && defined(HAVE___GETDIRENTRIES64) */
113
114#pragma pack(4)
115struct dirent32 {
116        ino_t d_ino;            /* file number of entry */
117        __uint16_t d_reclen;    /* length of this record */
118        __uint8_t  d_type;      /* file type */
119        __uint8_t  d_namlen;    /* length of string in d_name */
120        char d_name[__DARWIN_MAXNAMLEN + 1]; /* name must be no longer than this */
121};
122#pragma pack()
123
124static int _dt_getdirentries(int fd, char *buf, int nbytes, long *basep) {
125#define getdirentries(w,x,y,z) syscall(SYS_getdirentries, (w), (x), (y), (z))
126        __darwintrace_setup();
127
128        size_t sz = getdirentries(fd, buf, nbytes, basep);
129        char dirname[MAXPATHLEN];
130        size_t dnamelen;
131
132        if (-1 == fcntl(fd, F_GETPATH, dirname)) {
133                errno = EBADF;
134                return 0;
135        }
136
137        dnamelen = strlen(dirname);
138        if (dirname[dnamelen - 1] != '/') {
139                dirname[dnamelen] = '/';
140                dirname[dnamelen + 1] = '\0';
141                dnamelen++;
142        }
143
144        size_t offset;
145        for (offset = 0; offset < sz;) {
146                struct dirent32 *dent = (struct dirent32 *)(buf + offset);
147                dirname[dnamelen] = '\0';
148                strcat(dirname, dent->d_name);
149                if (!__darwintrace_is_in_sandbox(dirname, DT_ALLOWDIR)) {
150                        debug_printf("getdirentries: filtered %s\n", dirname);
151                        dent->d_ino = 0;
152                } else {
153                        debug_printf("getdirentries:  allowed %s\n", dirname);
154                }
155                offset += dent->d_reclen;
156        }
157
158        return sz;
159#undef getdirentries
160}
161
162int getdirentries(int fd, char *buf, int nbytes, long *basep);
163DARWINTRACE_INTERPOSE(_dt_getdirentries, getdirentries);
Note: See TracBrowser for help on using the repository browser.