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 
isLingerSocket(FileDescriptor fd)140     private static boolean isLingerSocket(FileDescriptor fd) throws ErrnoException {
141         StructLinger linger = Libcore.os.getsockoptLinger(fd, SOL_SOCKET, SO_LINGER);
142         return linger.isOn() && linger.l_linger > 0;
143     }
144 
isUdpSocket(FileDescriptor fd)145     private static boolean isUdpSocket(FileDescriptor fd) throws ErrnoException {
146         return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) == IPPROTO_UDP;
147     }
148 
connect(FileDescriptor fd, InetAddress address, int port)149     @Override public void connect(FileDescriptor fd, InetAddress address, int port)
150             throws ErrnoException, SocketException {
151         boolean skipGuard = false;
152         try {
153             skipGuard = isUdpSocket(fd);
154         } catch (ErrnoException ignored) {
155         }
156         if (!skipGuard) BlockGuard.getThreadPolicy().onNetwork();
157         super.connect(fd, address, port);
158     }
159 
connect(FileDescriptor fd, SocketAddress address)160     @Override public void connect(FileDescriptor fd, SocketAddress address) throws ErrnoException,
161             SocketException {
162         boolean skipGuard = false;
163         try {
164             skipGuard = isUdpSocket(fd);
165         } catch (ErrnoException ignored) {
166         }
167         if (!skipGuard) BlockGuard.getThreadPolicy().onNetwork();
168         super.connect(fd, address);
169     }
170 
171     @UnsupportedAppUsage
fchmod(FileDescriptor fd, int mode)172     @Override public void fchmod(FileDescriptor fd, int mode) throws ErrnoException {
173         BlockGuard.getThreadPolicy().onWriteToDisk();
174         super.fchmod(fd, mode);
175     }
176 
177     @UnsupportedAppUsage
fchown(FileDescriptor fd, int uid, int gid)178     @Override public void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException {
179         BlockGuard.getThreadPolicy().onWriteToDisk();
180         super.fchown(fd, uid, gid);
181     }
182 
183     // TODO: Untag newFd when needed for dup2(FileDescriptor oldFd, int newFd)
184 
185     @UnsupportedAppUsage
fdatasync(FileDescriptor fd)186     @Override public void fdatasync(FileDescriptor fd) throws ErrnoException {
187         BlockGuard.getThreadPolicy().onWriteToDisk();
188         super.fdatasync(fd);
189     }
190 
191     @UnsupportedAppUsage
fstat(FileDescriptor fd)192     @Override public StructStat fstat(FileDescriptor fd) throws ErrnoException {
193         BlockGuard.getThreadPolicy().onReadFromDisk();
194         return super.fstat(fd);
195     }
196 
197     @UnsupportedAppUsage
fstatvfs(FileDescriptor fd)198     @Override public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException {
199         BlockGuard.getThreadPolicy().onReadFromDisk();
200         return super.fstatvfs(fd);
201     }
202 
fsync(FileDescriptor fd)203     @Override public void fsync(FileDescriptor fd) throws ErrnoException {
204         BlockGuard.getThreadPolicy().onWriteToDisk();
205         super.fsync(fd);
206     }
207 
ftruncate(FileDescriptor fd, long length)208     @Override public void ftruncate(FileDescriptor fd, long length) throws ErrnoException {
209         BlockGuard.getThreadPolicy().onWriteToDisk();
210         super.ftruncate(fd, length);
211     }
212 
android_getaddrinfo(String node, StructAddrinfo hints, int netId)213     @Override public InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException {
214         // With AI_NUMERICHOST flag set, the node must a numerical network address, therefore no
215         // host address lookups will be performed. In this case, it is fine to perform on main
216         // thread.
217         boolean isNumericHost = (hints.ai_flags & AI_NUMERICHOST) != 0;
218         if (!isNumericHost) {
219             BlockGuard.getThreadPolicy().onNetwork();
220         }
221         return super.android_getaddrinfo(node, hints, netId);
222     }
223 
224     @UnsupportedAppUsage
lchown(String path, int uid, int gid)225     @Override public void lchown(String path, int uid, int gid) throws ErrnoException {
226         BlockGuard.getThreadPolicy().onWriteToDisk();
227         BlockGuard.getVmPolicy().onPathAccess(path);
228         super.lchown(path, uid, gid);
229     }
230 
231     @UnsupportedAppUsage
link(String oldPath, String newPath)232     @Override public void link(String oldPath, String newPath) throws ErrnoException {
233         BlockGuard.getThreadPolicy().onWriteToDisk();
234         BlockGuard.getVmPolicy().onPathAccess(oldPath);
235         BlockGuard.getVmPolicy().onPathAccess(newPath);
236         super.link(oldPath, newPath);
237     }
238 
239     @UnsupportedAppUsage
lseek(FileDescriptor fd, long offset, int whence)240     @Override public long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
241         BlockGuard.getThreadPolicy().onReadFromDisk();
242         return super.lseek(fd, offset, whence);
243     }
244 
245     @UnsupportedAppUsage
lstat(String path)246     @Override public StructStat lstat(String path) throws ErrnoException {
247         BlockGuard.getThreadPolicy().onReadFromDisk();
248         BlockGuard.getVmPolicy().onPathAccess(path);
249         return super.lstat(path);
250     }
251 
252     @UnsupportedAppUsage
mkdir(String path, int mode)253     @Override public void mkdir(String path, int mode) throws ErrnoException {
254         BlockGuard.getThreadPolicy().onWriteToDisk();
255         BlockGuard.getVmPolicy().onPathAccess(path);
256         super.mkdir(path, mode);
257     }
258 
259     @UnsupportedAppUsage
mkfifo(String path, int mode)260     @Override public void mkfifo(String path, int mode) throws ErrnoException {
261         BlockGuard.getThreadPolicy().onWriteToDisk();
262         BlockGuard.getVmPolicy().onPathAccess(path);
263         super.mkfifo(path, mode);
264     }
265 
266     @UnsupportedAppUsage
open(String path, int flags, int mode)267     @Override public FileDescriptor open(String path, int flags, int mode) throws ErrnoException {
268         BlockGuard.getThreadPolicy().onReadFromDisk();
269         BlockGuard.getVmPolicy().onPathAccess(path);
270         if ((flags & O_ACCMODE) != O_RDONLY) {
271             BlockGuard.getThreadPolicy().onWriteToDisk();
272         }
273         return super.open(path, flags, mode);
274     }
275 
poll(StructPollfd[] fds, int timeoutMs)276     @Override public int poll(StructPollfd[] fds, int timeoutMs) throws ErrnoException {
277         // Greater than 0 is a timeout in milliseconds and -1 means "block forever",
278         // but 0 means "poll and return immediately", which shouldn't be subject to BlockGuard.
279         if (timeoutMs != 0) {
280             BlockGuard.getThreadPolicy().onNetwork();
281         }
282         return super.poll(fds, timeoutMs);
283     }
284 
285     @UnsupportedAppUsage
posix_fallocate(FileDescriptor fd, long offset, long length)286     @Override public void posix_fallocate(FileDescriptor fd, long offset, long length) throws ErrnoException {
287         BlockGuard.getThreadPolicy().onWriteToDisk();
288         super.posix_fallocate(fd, offset, length);
289     }
290 
291     @UnsupportedAppUsage
pread(FileDescriptor fd, ByteBuffer buffer, long offset)292     @Override public int pread(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException {
293         BlockGuard.getThreadPolicy().onReadFromDisk();
294         return super.pread(fd, buffer, offset);
295     }
296 
297     @UnsupportedAppUsage
pread(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset)298     @Override public int pread(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException {
299         BlockGuard.getThreadPolicy().onReadFromDisk();
300         return super.pread(fd, bytes, byteOffset, byteCount, offset);
301     }
302 
303     @UnsupportedAppUsage
pwrite(FileDescriptor fd, ByteBuffer buffer, long offset)304     @Override public int pwrite(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException {
305         BlockGuard.getThreadPolicy().onWriteToDisk();
306         return super.pwrite(fd, buffer, offset);
307     }
308 
309     @UnsupportedAppUsage
pwrite(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset)310     @Override public int pwrite(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException {
311         BlockGuard.getThreadPolicy().onWriteToDisk();
312         return super.pwrite(fd, bytes, byteOffset, byteCount, offset);
313     }
314 
315     @UnsupportedAppUsage
read(FileDescriptor fd, ByteBuffer buffer)316     @Override public int read(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException {
317         BlockGuard.getThreadPolicy().onReadFromDisk();
318         return super.read(fd, buffer);
319     }
320 
321     @UnsupportedAppUsage
read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount)322     @Override public int read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException {
323         BlockGuard.getThreadPolicy().onReadFromDisk();
324         return super.read(fd, bytes, byteOffset, byteCount);
325     }
326 
327     @UnsupportedAppUsage
readlink(String path)328     @Override public String readlink(String path) throws ErrnoException {
329       BlockGuard.getThreadPolicy().onReadFromDisk();
330       BlockGuard.getVmPolicy().onPathAccess(path);
331       return super.readlink(path);
332     }
333 
334     @UnsupportedAppUsage
realpath(String path)335     @Override public String realpath(String path) throws ErrnoException {
336       BlockGuard.getThreadPolicy().onReadFromDisk();
337       BlockGuard.getVmPolicy().onPathAccess(path);
338       return super.realpath(path);
339     }
340 
341     @UnsupportedAppUsage
readv(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts)342     @Override public int readv(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException {
343         BlockGuard.getThreadPolicy().onReadFromDisk();
344         return super.readv(fd, buffers, offsets, byteCounts);
345     }
346 
recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress)347     @Override public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException {
348         BlockGuard.getThreadPolicy().onNetwork();
349         return super.recvfrom(fd, buffer, flags, srcAddress);
350     }
351 
recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress)352     @Override public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException {
353         BlockGuard.getThreadPolicy().onNetwork();
354         return super.recvfrom(fd, bytes, byteOffset, byteCount, flags, srcAddress);
355     }
356 
recvmsg(FileDescriptor fd, StructMsghdr msg, int flags)357     @Override public int recvmsg(FileDescriptor fd, StructMsghdr msg, int flags) throws ErrnoException, SocketException {
358         BlockGuard.getThreadPolicy().onNetwork();
359         return super.recvmsg(fd, msg, flags);
360     }
361 
362     @UnsupportedAppUsage
remove(String path)363     @Override public void remove(String path) throws ErrnoException {
364         BlockGuard.getThreadPolicy().onWriteToDisk();
365         BlockGuard.getVmPolicy().onPathAccess(path);
366         super.remove(path);
367     }
368 
369     @UnsupportedAppUsage
rename(String oldPath, String newPath)370     @Override public void rename(String oldPath, String newPath) throws ErrnoException {
371         BlockGuard.getThreadPolicy().onWriteToDisk();
372         BlockGuard.getVmPolicy().onPathAccess(oldPath);
373         BlockGuard.getVmPolicy().onPathAccess(newPath);
374         super.rename(oldPath, newPath);
375     }
376 
sendfile(FileDescriptor outFd, FileDescriptor inFd, Int64Ref offset, long byteCount)377     @Override public long sendfile(FileDescriptor outFd, FileDescriptor inFd, Int64Ref offset, long byteCount) throws ErrnoException {
378         BlockGuard.getThreadPolicy().onWriteToDisk();
379         return super.sendfile(outFd, inFd, offset, byteCount);
380     }
381 
sendmsg(FileDescriptor fd, StructMsghdr msg, int flags)382     @Override public int sendmsg(FileDescriptor fd, StructMsghdr msg, int flags) throws ErrnoException, SocketException {
383         BlockGuard.getThreadPolicy().onNetwork();
384         return super.sendmsg(fd, msg, flags);
385     }
386 
sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port)387     @Override public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException {
388         BlockGuard.getThreadPolicy().onNetwork();
389         return super.sendto(fd, buffer, flags, inetAddress, port);
390     }
391 
sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port)392     @Override public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException {
393         // We permit datagrams without hostname lookups.
394         if (inetAddress != null) {
395             BlockGuard.getThreadPolicy().onNetwork();
396         }
397         return super.sendto(fd, bytes, byteOffset, byteCount, flags, inetAddress, port);
398     }
399 
socket(int domain, int type, int protocol)400     @Override public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException {
401         final FileDescriptor fd = super.socket(domain, type, protocol);
402         if (isInetDomain(domain)) {
403             tagSocket(fd);
404         }
405         return fd;
406     }
407 
socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2)408     @Override public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException {
409         super.socketpair(domain, type, protocol, fd1, fd2);
410         if (isInetDomain(domain)) {
411             tagSocket(fd1);
412             tagSocket(fd2);
413         }
414     }
415 
416     @UnsupportedAppUsage
stat(String path)417     @Override public StructStat stat(String path) throws ErrnoException {
418         BlockGuard.getThreadPolicy().onReadFromDisk();
419         BlockGuard.getVmPolicy().onPathAccess(path);
420         return super.stat(path);
421     }
422 
423     @UnsupportedAppUsage
statvfs(String path)424     @Override public StructStatVfs statvfs(String path) throws ErrnoException {
425         BlockGuard.getThreadPolicy().onReadFromDisk();
426         BlockGuard.getVmPolicy().onPathAccess(path);
427         return super.statvfs(path);
428     }
429 
430     @UnsupportedAppUsage
symlink(String oldPath, String newPath)431     @Override public void symlink(String oldPath, String newPath) throws ErrnoException {
432         BlockGuard.getThreadPolicy().onWriteToDisk();
433         BlockGuard.getVmPolicy().onPathAccess(oldPath);
434         BlockGuard.getVmPolicy().onPathAccess(newPath);
435         super.symlink(oldPath, newPath);
436     }
437 
438     @UnsupportedAppUsage
write(FileDescriptor fd, ByteBuffer buffer)439     @Override public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException {
440         BlockGuard.getThreadPolicy().onWriteToDisk();
441         return super.write(fd, buffer);
442     }
443 
444     @UnsupportedAppUsage
write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount)445     @Override public int write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException {
446         BlockGuard.getThreadPolicy().onWriteToDisk();
447         return super.write(fd, bytes, byteOffset, byteCount);
448     }
449 
450     @UnsupportedAppUsage
writev(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts)451     @Override public int writev(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException {
452         BlockGuard.getThreadPolicy().onWriteToDisk();
453         return super.writev(fd, buffers, offsets, byteCounts);
454     }
455 
execv(String filename, String[] argv)456     @Override public void execv(String filename, String[] argv) throws ErrnoException {
457         BlockGuard.getThreadPolicy().onReadFromDisk();
458         BlockGuard.getVmPolicy().onPathAccess(filename);
459         super.execv(filename, argv);
460     }
461 
execve(String filename, String[] argv, String[] envp)462     @Override public void execve(String filename, String[] argv, String[] envp)
463             throws ErrnoException {
464         BlockGuard.getThreadPolicy().onReadFromDisk();
465         BlockGuard.getVmPolicy().onPathAccess(filename);
466         super.execve(filename, argv, envp);
467     }
468 
getxattr(String path, String name)469     @Override public byte[] getxattr(String path, String name) throws ErrnoException {
470         BlockGuard.getThreadPolicy().onReadFromDisk();
471         BlockGuard.getVmPolicy().onPathAccess(path);
472         return super.getxattr(path, name);
473     }
474 
msync(long address, long byteCount, int flags)475     @Override public void msync(long address, long byteCount, int flags) throws ErrnoException {
476         if ((flags & OsConstants.MS_SYNC) != 0) {
477             BlockGuard.getThreadPolicy().onWriteToDisk();
478         }
479         super.msync(address, byteCount, flags);
480     }
481 
removexattr(String path, String name)482     @Override public void removexattr(String path, String name) throws ErrnoException {
483         BlockGuard.getThreadPolicy().onWriteToDisk();
484         BlockGuard.getVmPolicy().onPathAccess(path);
485         super.removexattr(path, name);
486     }
487 
setxattr(String path, String name, byte[] value, int flags)488     @Override public void setxattr(String path, String name, byte[] value, int flags)
489             throws ErrnoException {
490         BlockGuard.getThreadPolicy().onWriteToDisk();
491         BlockGuard.getVmPolicy().onPathAccess(path);
492         super.setxattr(path, name, value, flags);
493     }
494 
sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, SocketAddress address)495     @Override public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount,
496             int flags, SocketAddress address) throws ErrnoException, SocketException {
497         BlockGuard.getThreadPolicy().onNetwork();
498         return super.sendto(fd, bytes, byteOffset, byteCount, flags, address);
499     }
500 
unlink(String pathname)501     @Override public void unlink(String pathname) throws ErrnoException {
502         BlockGuard.getThreadPolicy().onWriteToDisk();
503         BlockGuard.getVmPolicy().onPathAccess(pathname);
504         super.unlink(pathname);
505     }
506 
splice(FileDescriptor fdIn, Int64Ref offIn, FileDescriptor fdOut, Int64Ref offOut, long len, int flags)507     @Override public long splice(FileDescriptor fdIn, Int64Ref offIn, FileDescriptor fdOut, Int64Ref offOut, long len, int flags) throws ErrnoException {
508         // It's infeasible to figure out if splice will result in read or write (would require fstat to figure out which fd is pipe).
509         // So, signal both read and write.
510         BlockGuard.getThreadPolicy().onWriteToDisk();
511         BlockGuard.getThreadPolicy().onReadFromDisk();
512         return super.splice(fdIn, offIn, fdOut, offOut, len, flags);
513     }
514 }
515