1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package libcore.io;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 import android.system.ErrnoException;
21 import android.system.GaiException;
22 import android.system.Int64Ref;
23 import android.system.OsConstants;
24 import android.system.StructAddrinfo;
25 import android.system.StructLinger;
26 import android.system.StructMsghdr;
27 import android.system.StructPollfd;
28 import android.system.StructStat;
29 import android.system.StructStatVfs;
30 
31 import java.io.FileDescriptor;
32 import java.io.InterruptedIOException;
33 import java.net.InetAddress;
34 import java.net.InetSocketAddress;
35 import java.net.SocketAddress;
36 import java.net.SocketException;
37 import java.nio.ByteBuffer;
38 
39 import dalvik.system.BlockGuard;
40 import dalvik.system.SocketTagger;
41 
42 import static android.system.OsConstants.*;
43 
44 /**
45  * Informs BlockGuard of any activity it should be aware of.
46  */
47 public class BlockGuardOs extends ForwardingOs {
48     @UnsupportedAppUsage
BlockGuardOs(Os os)49     public BlockGuardOs(Os os) {
50         super(os);
51     }
52 
tagSocket(FileDescriptor fd)53     private FileDescriptor tagSocket(FileDescriptor fd) throws ErrnoException {
54         try {
55             SocketTagger.get().tag(fd);
56             return fd;
57         } catch (SocketException e) {
58             throw new ErrnoException("socket", EINVAL, e);
59         }
60     }
61 
accept(FileDescriptor fd, SocketAddress peerAddress)62     @Override public FileDescriptor accept(FileDescriptor fd, SocketAddress peerAddress) throws ErrnoException, SocketException {
63         if (!(isUnixSocket(fd) && isNonBlockingFile(fd))) {
64             BlockGuard.getThreadPolicy().onNetwork();
65         }
66         final FileDescriptor acceptFd = super.accept(fd, peerAddress);
67         if (acceptFd != null && isInetSocket(acceptFd)) {
68             tagSocket(acceptFd);
69         }
70         return acceptFd;
71     }
72 
access(String path, int mode)73     @Override public boolean access(String path, int mode) throws ErrnoException {
74         BlockGuard.getThreadPolicy().onReadFromDisk();
75         BlockGuard.getVmPolicy().onPathAccess(path);
76         return super.access(path, mode);
77     }
78 
79     @UnsupportedAppUsage
chmod(String path, int mode)80     @Override public void chmod(String path, int mode) throws ErrnoException {
81         BlockGuard.getThreadPolicy().onWriteToDisk();
82         BlockGuard.getVmPolicy().onPathAccess(path);
83         super.chmod(path, mode);
84     }
85 
86     @UnsupportedAppUsage
chown(String path, int uid, int gid)87     @Override public void chown(String path, int uid, int gid) throws ErrnoException {
88         BlockGuard.getThreadPolicy().onWriteToDisk();
89         BlockGuard.getVmPolicy().onPathAccess(path);
90         super.chown(path, uid, gid);
91     }
92 
93     @UnsupportedAppUsage
close(FileDescriptor fd)94     @Override public void close(FileDescriptor fd) throws ErrnoException {
95         try {
96             // The usual case is that this _isn't_ a socket, so the getsockopt(2) call in
97             // isLingerSocket will throw, and that's really expensive. Try to avoid asking
98             // if we don't care.
99             if (fd.isSocket$()) {
100                 if (isLingerSocket(fd)) {
101                     // If the fd is a socket with SO_LINGER set, we might block indefinitely.
102                     // We allow non-linger sockets so that apps can close their network
103                     // connections in methods like onDestroy which will run on the UI thread.
104                     BlockGuard.getThreadPolicy().onNetwork();
105                 }
106             }
107         } catch (ErrnoException ignored) {
108             // We're called via Socket.close (which doesn't ask for us to be called), so we
109             // must not throw here, because Socket.close must not throw if asked to close an
110             // already-closed socket. Also, the passed-in FileDescriptor isn't necessarily
111             // a socket at all.
112         }
113         super.close(fd);
114     }
115 
isNonBlockingFile(FileDescriptor fd)116     public static boolean isNonBlockingFile(FileDescriptor fd) throws ErrnoException {
117         int flag = android.system.Os.fcntlInt(fd, F_GETFL, 0);
118         if ((flag & O_NONBLOCK) != 0) {
119             return true;
120         }
121         return false;
122     }
123 
isUnixSocket(FileDescriptor fd)124     public static boolean isUnixSocket(FileDescriptor fd) throws ErrnoException {
125         return isUnixDomain(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_DOMAIN));
126     }
127 
isUnixDomain(int domain)128     private static boolean isUnixDomain(int domain) {
129         return (domain == AF_UNIX);
130     }
131 
isInetSocket(FileDescriptor fd)132     private static boolean isInetSocket(FileDescriptor fd) throws ErrnoException{
133         return isInetDomain(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_DOMAIN));
134     }
135 
isInetDomain(int domain)136     private static boolean isInetDomain(int domain) {
137         return (domain == AF_INET) || (domain == AF_INET6);
138     }
139 
140     @SuppressWarnings("NewApi") // False positive lint limitation, see b/177434707.
isLingerSocket(FileDescriptor fd)141     private static boolean isLingerSocket(FileDescriptor fd) throws ErrnoException {
142         StructLinger linger = Libcore.os.getsockoptLinger(fd, SOL_SOCKET, SO_LINGER);
143         return linger.isOn() && linger.l_linger > 0;
144     }
145 
isUdpSocket(FileDescriptor fd)146     private static boolean isUdpSocket(FileDescriptor fd) throws ErrnoException {
147         return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) == IPPROTO_UDP;
148     }
149 
connect(FileDescriptor fd, InetAddress address, int port)150     @Override public void connect(FileDescriptor fd, InetAddress address, int port)
151             throws ErrnoException, SocketException {
152         boolean skipGuard = false;
153         try {
154             skipGuard = isUdpSocket(fd);
155         } catch (ErrnoException ignored) {
156         }
157         if (!skipGuard) BlockGuard.getThreadPolicy().onNetwork();
158         super.connect(fd, address, port);
159     }
160 
connect(FileDescriptor fd, SocketAddress address)161     @Override public void connect(FileDescriptor fd, SocketAddress address) throws ErrnoException,
162             SocketException {
163         boolean skipGuard = false;
164         try {
165             skipGuard = isUdpSocket(fd);
166         } catch (ErrnoException ignored) {
167         }
168         if (!skipGuard) BlockGuard.getThreadPolicy().onNetwork();
169         super.connect(fd, address);
170     }
171 
172     @UnsupportedAppUsage
fchmod(FileDescriptor fd, int mode)173     @Override public void fchmod(FileDescriptor fd, int mode) throws ErrnoException {
174         BlockGuard.getThreadPolicy().onWriteToDisk();
175         super.fchmod(fd, mode);
176     }
177 
178     @UnsupportedAppUsage
fchown(FileDescriptor fd, int uid, int gid)179     @Override public void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException {
180         BlockGuard.getThreadPolicy().onWriteToDisk();
181         super.fchown(fd, uid, gid);
182     }
183 
184     // TODO: Untag newFd when needed for dup2(FileDescriptor oldFd, int newFd)
185 
186     @UnsupportedAppUsage
fdatasync(FileDescriptor fd)187     @Override public void fdatasync(FileDescriptor fd) throws ErrnoException {
188         BlockGuard.getThreadPolicy().onWriteToDisk();
189         super.fdatasync(fd);
190     }
191 
192     @UnsupportedAppUsage
fstat(FileDescriptor fd)193     @Override public StructStat fstat(FileDescriptor fd) throws ErrnoException {
194         BlockGuard.getThreadPolicy().onReadFromDisk();
195         return super.fstat(fd);
196     }
197 
198     @UnsupportedAppUsage
fstatvfs(FileDescriptor fd)199     @Override public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException {
200         BlockGuard.getThreadPolicy().onReadFromDisk();
201         return super.fstatvfs(fd);
202     }
203 
fsync(FileDescriptor fd)204     @Override public void fsync(FileDescriptor fd) throws ErrnoException {
205         BlockGuard.getThreadPolicy().onWriteToDisk();
206         super.fsync(fd);
207     }
208 
ftruncate(FileDescriptor fd, long length)209     @Override public void ftruncate(FileDescriptor fd, long length) throws ErrnoException {
210         BlockGuard.getThreadPolicy().onWriteToDisk();
211         super.ftruncate(fd, length);
212     }
213 
android_getaddrinfo(String node, StructAddrinfo hints, int netId)214     @Override public InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException {
215         // With AI_NUMERICHOST flag set, the node must a numerical network address, therefore no
216         // host address lookups will be performed. In this case, it is fine to perform on main
217         // thread.
218         boolean isNumericHost = (hints.ai_flags & AI_NUMERICHOST) != 0;
219         if (!isNumericHost) {
220             BlockGuard.getThreadPolicy().onNetwork();
221         }
222         return super.android_getaddrinfo(node, hints, netId);
223     }
224 
225     @UnsupportedAppUsage
lchown(String path, int uid, int gid)226     @Override public void lchown(String path, int uid, int gid) throws ErrnoException {
227         BlockGuard.getThreadPolicy().onWriteToDisk();
228         BlockGuard.getVmPolicy().onPathAccess(path);
229         super.lchown(path, uid, gid);
230     }
231 
232     @UnsupportedAppUsage
link(String oldPath, String newPath)233     @Override public void link(String oldPath, String newPath) throws ErrnoException {
234         BlockGuard.getThreadPolicy().onWriteToDisk();
235         BlockGuard.getVmPolicy().onPathAccess(oldPath);
236         BlockGuard.getVmPolicy().onPathAccess(newPath);
237         super.link(oldPath, newPath);
238     }
239 
240     @UnsupportedAppUsage
lseek(FileDescriptor fd, long offset, int whence)241     @Override public long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
242         BlockGuard.getThreadPolicy().onReadFromDisk();
243         return super.lseek(fd, offset, whence);
244     }
245 
246     @UnsupportedAppUsage
lstat(String path)247     @Override public StructStat lstat(String path) throws ErrnoException {
248         BlockGuard.getThreadPolicy().onReadFromDisk();
249         BlockGuard.getVmPolicy().onPathAccess(path);
250         return super.lstat(path);
251     }
252 
253     @UnsupportedAppUsage
mkdir(String path, int mode)254     @Override public void mkdir(String path, int mode) throws ErrnoException {
255         BlockGuard.getThreadPolicy().onWriteToDisk();
256         BlockGuard.getVmPolicy().onPathAccess(path);
257         super.mkdir(path, mode);
258     }
259 
260     @UnsupportedAppUsage
mkfifo(String path, int mode)261     @Override public void mkfifo(String path, int mode) throws ErrnoException {
262         BlockGuard.getThreadPolicy().onWriteToDisk();
263         BlockGuard.getVmPolicy().onPathAccess(path);
264         super.mkfifo(path, mode);
265     }
266 
267     @UnsupportedAppUsage
open(String path, int flags, int mode)268     @Override public FileDescriptor open(String path, int flags, int mode) throws ErrnoException {
269         BlockGuard.getThreadPolicy().onReadFromDisk();
270         BlockGuard.getVmPolicy().onPathAccess(path);
271         if ((flags & O_ACCMODE) != O_RDONLY) {
272             BlockGuard.getThreadPolicy().onWriteToDisk();
273         }
274         return super.open(path, flags, mode);
275     }
276 
poll(StructPollfd[] fds, int timeoutMs)277     @Override public int poll(StructPollfd[] fds, int timeoutMs) throws ErrnoException {
278         // Greater than 0 is a timeout in milliseconds and -1 means "block forever",
279         // but 0 means "poll and return immediately", which shouldn't be subject to BlockGuard.
280         if (timeoutMs != 0) {
281             BlockGuard.getThreadPolicy().onNetwork();
282         }
283         return super.poll(fds, timeoutMs);
284     }
285 
286     @UnsupportedAppUsage
posix_fallocate(FileDescriptor fd, long offset, long length)287     @Override public void posix_fallocate(FileDescriptor fd, long offset, long length) throws ErrnoException {
288         BlockGuard.getThreadPolicy().onWriteToDisk();
289         super.posix_fallocate(fd, offset, length);
290     }
291 
292     @UnsupportedAppUsage
pread(FileDescriptor fd, ByteBuffer buffer, long offset)293     @Override public int pread(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException {
294         BlockGuard.getThreadPolicy().onReadFromDisk();
295         return super.pread(fd, buffer, offset);
296     }
297 
298     @UnsupportedAppUsage
pread(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset)299     @Override public int pread(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException {
300         BlockGuard.getThreadPolicy().onReadFromDisk();
301         return super.pread(fd, bytes, byteOffset, byteCount, offset);
302     }
303 
304     @UnsupportedAppUsage
pwrite(FileDescriptor fd, ByteBuffer buffer, long offset)305     @Override public int pwrite(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException {
306         BlockGuard.getThreadPolicy().onWriteToDisk();
307         return super.pwrite(fd, buffer, offset);
308     }
309 
310     @UnsupportedAppUsage
pwrite(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset)311     @Override public int pwrite(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException {
312         BlockGuard.getThreadPolicy().onWriteToDisk();
313         return super.pwrite(fd, bytes, byteOffset, byteCount, offset);
314     }
315 
316     @UnsupportedAppUsage
read(FileDescriptor fd, ByteBuffer buffer)317     @Override public int read(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException {
318         BlockGuard.getThreadPolicy().onReadFromDisk();
319         return super.read(fd, buffer);
320     }
321 
322     @UnsupportedAppUsage
read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount)323     @Override public int read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException {
324         BlockGuard.getThreadPolicy().onReadFromDisk();
325         return super.read(fd, bytes, byteOffset, byteCount);
326     }
327 
328     @UnsupportedAppUsage
readlink(String path)329     @Override public String readlink(String path) throws ErrnoException {
330       BlockGuard.getThreadPolicy().onReadFromDisk();
331       BlockGuard.getVmPolicy().onPathAccess(path);
332       return super.readlink(path);
333     }
334 
335     @UnsupportedAppUsage
realpath(String path)336     @Override public String realpath(String path) throws ErrnoException {
337       BlockGuard.getThreadPolicy().onReadFromDisk();
338       BlockGuard.getVmPolicy().onPathAccess(path);
339       return super.realpath(path);
340     }
341 
342     @UnsupportedAppUsage
readv(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts)343     @Override public int readv(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException {
344         BlockGuard.getThreadPolicy().onReadFromDisk();
345         return super.readv(fd, buffers, offsets, byteCounts);
346     }
347 
recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress)348     @Override public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException {
349         BlockGuard.getThreadPolicy().onNetwork();
350         return super.recvfrom(fd, buffer, flags, srcAddress);
351     }
352 
recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress)353     @Override public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException {
354         BlockGuard.getThreadPolicy().onNetwork();
355         return super.recvfrom(fd, bytes, byteOffset, byteCount, flags, srcAddress);
356     }
357 
recvmsg(FileDescriptor fd, StructMsghdr msg, int flags)358     @Override public int recvmsg(FileDescriptor fd, StructMsghdr msg, int flags) throws ErrnoException, SocketException {
359         BlockGuard.getThreadPolicy().onNetwork();
360         return super.recvmsg(fd, msg, flags);
361     }
362 
363     @UnsupportedAppUsage
remove(String path)364     @Override public void remove(String path) throws ErrnoException {
365         BlockGuard.getThreadPolicy().onWriteToDisk();
366         BlockGuard.getVmPolicy().onPathAccess(path);
367         super.remove(path);
368     }
369 
370     @UnsupportedAppUsage
rename(String oldPath, String newPath)371     @Override public void rename(String oldPath, String newPath) throws ErrnoException {
372         BlockGuard.getThreadPolicy().onWriteToDisk();
373         BlockGuard.getVmPolicy().onPathAccess(oldPath);
374         BlockGuard.getVmPolicy().onPathAccess(newPath);
375         super.rename(oldPath, newPath);
376     }
377 
sendfile(FileDescriptor outFd, FileDescriptor inFd, Int64Ref offset, long byteCount)378     @Override public long sendfile(FileDescriptor outFd, FileDescriptor inFd, Int64Ref offset, long byteCount) throws ErrnoException {
379         BlockGuard.getThreadPolicy().onWriteToDisk();
380         return super.sendfile(outFd, inFd, offset, byteCount);
381     }
382 
sendmsg(FileDescriptor fd, StructMsghdr msg, int flags)383     @Override public int sendmsg(FileDescriptor fd, StructMsghdr msg, int flags) throws ErrnoException, SocketException {
384         BlockGuard.getThreadPolicy().onNetwork();
385         return super.sendmsg(fd, msg, flags);
386     }
387 
sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port)388     @Override public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException {
389         BlockGuard.getThreadPolicy().onNetwork();
390         return super.sendto(fd, buffer, flags, inetAddress, port);
391     }
392 
sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port)393     @Override public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException {
394         // We permit datagrams without hostname lookups.
395         if (inetAddress != null) {
396             BlockGuard.getThreadPolicy().onNetwork();
397         }
398         return super.sendto(fd, bytes, byteOffset, byteCount, flags, inetAddress, port);
399     }
400 
socket(int domain, int type, int protocol)401     @Override public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException {
402         final FileDescriptor fd = super.socket(domain, type, protocol);
403         if (isInetDomain(domain)) {
404             tagSocket(fd);
405         }
406         return fd;
407     }
408 
socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2)409     @Override public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException {
410         super.socketpair(domain, type, protocol, fd1, fd2);
411         if (isInetDomain(domain)) {
412             tagSocket(fd1);
413             tagSocket(fd2);
414         }
415     }
416 
417     @UnsupportedAppUsage
stat(String path)418     @Override public StructStat stat(String path) throws ErrnoException {
419         BlockGuard.getThreadPolicy().onReadFromDisk();
420         BlockGuard.getVmPolicy().onPathAccess(path);
421         return super.stat(path);
422     }
423 
424     @UnsupportedAppUsage
statvfs(String path)425     @Override public StructStatVfs statvfs(String path) throws ErrnoException {
426         BlockGuard.getThreadPolicy().onReadFromDisk();
427         BlockGuard.getVmPolicy().onPathAccess(path);
428         return super.statvfs(path);
429     }
430 
431     @UnsupportedAppUsage
symlink(String oldPath, String newPath)432     @Override public void symlink(String oldPath, String newPath) throws ErrnoException {
433         BlockGuard.getThreadPolicy().onWriteToDisk();
434         BlockGuard.getVmPolicy().onPathAccess(oldPath);
435         BlockGuard.getVmPolicy().onPathAccess(newPath);
436         super.symlink(oldPath, newPath);
437     }
438 
439     @UnsupportedAppUsage
write(FileDescriptor fd, ByteBuffer buffer)440     @Override public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException {
441         BlockGuard.getThreadPolicy().onWriteToDisk();
442         return super.write(fd, buffer);
443     }
444 
445     @UnsupportedAppUsage
write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount)446     @Override public int write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException {
447         BlockGuard.getThreadPolicy().onWriteToDisk();
448         return super.write(fd, bytes, byteOffset, byteCount);
449     }
450 
451     @UnsupportedAppUsage
writev(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts)452     @Override public int writev(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException {
453         BlockGuard.getThreadPolicy().onWriteToDisk();
454         return super.writev(fd, buffers, offsets, byteCounts);
455     }
456 
execv(String filename, String[] argv)457     @Override public void execv(String filename, String[] argv) throws ErrnoException {
458         BlockGuard.getThreadPolicy().onReadFromDisk();
459         BlockGuard.getVmPolicy().onPathAccess(filename);
460         super.execv(filename, argv);
461     }
462 
execve(String filename, String[] argv, String[] envp)463     @Override public void execve(String filename, String[] argv, String[] envp)
464             throws ErrnoException {
465         BlockGuard.getThreadPolicy().onReadFromDisk();
466         BlockGuard.getVmPolicy().onPathAccess(filename);
467         super.execve(filename, argv, envp);
468     }
469 
getxattr(String path, String name)470     @Override public byte[] getxattr(String path, String name) throws ErrnoException {
471         BlockGuard.getThreadPolicy().onReadFromDisk();
472         BlockGuard.getVmPolicy().onPathAccess(path);
473         return super.getxattr(path, name);
474     }
475 
msync(long address, long byteCount, int flags)476     @Override public void msync(long address, long byteCount, int flags) throws ErrnoException {
477         if ((flags & OsConstants.MS_SYNC) != 0) {
478             BlockGuard.getThreadPolicy().onWriteToDisk();
479         }
480         super.msync(address, byteCount, flags);
481     }
482 
removexattr(String path, String name)483     @Override public void removexattr(String path, String name) throws ErrnoException {
484         BlockGuard.getThreadPolicy().onWriteToDisk();
485         BlockGuard.getVmPolicy().onPathAccess(path);
486         super.removexattr(path, name);
487     }
488 
setxattr(String path, String name, byte[] value, int flags)489     @Override public void setxattr(String path, String name, byte[] value, int flags)
490             throws ErrnoException {
491         BlockGuard.getThreadPolicy().onWriteToDisk();
492         BlockGuard.getVmPolicy().onPathAccess(path);
493         super.setxattr(path, name, value, flags);
494     }
495 
sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, SocketAddress address)496     @Override public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount,
497             int flags, SocketAddress address) throws ErrnoException, SocketException {
498         BlockGuard.getThreadPolicy().onNetwork();
499         return super.sendto(fd, bytes, byteOffset, byteCount, flags, address);
500     }
501 
unlink(String pathname)502     @Override public void unlink(String pathname) throws ErrnoException {
503         BlockGuard.getThreadPolicy().onWriteToDisk();
504         BlockGuard.getVmPolicy().onPathAccess(pathname);
505         super.unlink(pathname);
506     }
507 
splice(FileDescriptor fdIn, Int64Ref offIn, FileDescriptor fdOut, Int64Ref offOut, long len, int flags)508     @Override public long splice(FileDescriptor fdIn, Int64Ref offIn, FileDescriptor fdOut, Int64Ref offOut, long len, int flags) throws ErrnoException {
509         // It's infeasible to figure out if splice will result in read or write (would require fstat to figure out which fd is pipe).
510         // So, signal both read and write.
511         BlockGuard.getThreadPolicy().onWriteToDisk();
512         BlockGuard.getThreadPolicy().onReadFromDisk();
513         return super.splice(fdIn, offIn, fdOut, offOut, len, flags);
514     }
515 }
516