1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
/*
* SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
*
* For a successful call, the return value depends on the operation:
*
* F_DUPFD The new descriptor.
* F_GETFD Value of file descriptor flags.
* F_GETFL Value of file status flags.
* F_GETLEASE Type of lease held on file descriptor.
* F_GETOWN Value of descriptor owner.
* F_GETSIG Value of signal sent when read or write becomes possible, or zero for traditional SIGIO behavior.
* F_GETPIPE_SZ The pipe capacity.
*
* All other commands
* Zero.
*
* On error, -1 is returned, and errno is set appropriately.
*/
#include <fcntl.h>
#include <signal.h>
#include "random.h"
#include "sanitise.h"
#include "shm.h"
#include "compat.h"
#if F_GETLK64 != F_GETLK
#define HAVE_LK64
#endif
static void sanitise_fcntl(int childno)
{
switch (shm->a2[childno]) {
/* arg = fd */
case F_DUPFD:
case F_DUPFD_CLOEXEC:
case F_SETLEASE:
shm->a3[childno] = (unsigned long) get_random_fd();
break;
/* no arg */
case F_GETFD:
case F_GETFL:
case F_GETOWN:
case F_GETSIG:
case F_GETLEASE:
case F_GETPIPE_SZ:
case F_GETOWNER_UIDS:
break;
case F_SETFD: /* arg = flags */
shm->a3[childno] = (unsigned int) rand32();
break;
case F_SETFL:
shm->a3[childno] = 0L;
if (rand_bool())
shm->a3[childno] |= O_APPEND;
if (rand_bool())
shm->a3[childno] |= O_ASYNC;
if (rand_bool())
shm->a3[childno] |= O_DIRECT;
if (rand_bool())
shm->a3[childno] |= O_NOATIME;
if (rand_bool())
shm->a3[childno] |= O_NONBLOCK;
break;
/* arg = (struct flock *) */
case F_GETLK:
case F_SETLK:
case F_SETLKW:
break;
#ifdef HAVE_LK64
case F_GETLK64:
break;
case F_SETLK64:
break;
case F_SETLKW64:
break;
#endif
case F_SETOWN:
shm->a3[childno] = (unsigned long) get_pid();
break;
/* arg = struct f_owner_ex *) */
case F_GETOWN_EX:
case F_SETOWN_EX:
break;
case F_SETSIG:
shm->a3[childno] = (unsigned long) rand32();
if (shm->a3[childno] == SIGINT)
shm->a3[childno] = 0; /* restore default (SIGIO) */
break;
case F_NOTIFY:
shm->a3[childno] = 0L;
if (rand_bool())
shm->a3[childno] |= DN_ACCESS;
if (rand_bool())
shm->a3[childno] |= DN_MODIFY;
if (rand_bool())
shm->a3[childno] |= DN_CREATE;
if (rand_bool())
shm->a3[childno] |= DN_DELETE;
if (rand_bool())
shm->a3[childno] |= DN_RENAME;
if (rand_bool())
shm->a3[childno] |= DN_ATTRIB;
break;
case F_SETPIPE_SZ:
shm->a3[childno] = rand32();
break;
default:
break;
}
}
struct syscall syscall_fcntl = {
.name = "fcntl",
.num_args = 3,
.arg1name = "fd",
.arg1type = ARG_FD,
.arg2name = "cmd",
.arg2type = ARG_OP,
.arg2list = {
#ifndef HAVE_LK64
.num = 21,
#else
.num = 24,
#endif
.values = { F_DUPFD, F_DUPFD_CLOEXEC, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK,
F_SETLKW, F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG, F_SETSIG, F_GETLEASE,
F_SETLEASE, F_NOTIFY, F_SETPIPE_SZ, F_GETPIPE_SZ, F_GETOWNER_UIDS,
#ifdef HAVE_LK64
F_GETLK64, F_SETLK64, F_SETLKW64,
#endif
},
},
.arg3name = "arg",
.rettype = RET_FD, //FIXME: Needs to mutate somehow depending on 'cmd'
.flags = NEED_ALARM,
.group = GROUP_VFS,
.sanitise = sanitise_fcntl,
};
|