/** {@inheritDoc} */ @Override public long[][] getProcessorCpuLoadTicks() { long[][] ticks = new long[logicalProcessorCount][4]; int machPort = SystemB.INSTANCE.mach_host_self(); IntByReference procCount = new IntByReference(); PointerByReference procCpuLoadInfo = new PointerByReference(); IntByReference procInfoCount = new IntByReference(); if (0 != SystemB.INSTANCE.host_processor_info( machPort, SystemB.PROCESSOR_CPU_LOAD_INFO, procCount, procCpuLoadInfo, procInfoCount)) { LOG.error("Failed to update CPU Load. Error code: " + Native.getLastError()); return ticks; } int[] cpuTicks = procCpuLoadInfo.getValue().getIntArray(0, procInfoCount.getValue()); for (int cpu = 0; cpu < procCount.getValue(); cpu++) { for (int j = 0; j < 4; j++) { int offset = cpu * SystemB.CPU_STATE_MAX; ticks[cpu][0] = FormatUtil.getUnsignedInt(cpuTicks[offset + SystemB.CPU_STATE_USER]); ticks[cpu][1] = FormatUtil.getUnsignedInt(cpuTicks[offset + SystemB.CPU_STATE_NICE]); ticks[cpu][2] = FormatUtil.getUnsignedInt(cpuTicks[offset + SystemB.CPU_STATE_SYSTEM]); ticks[cpu][3] = FormatUtil.getUnsignedInt(cpuTicks[offset + SystemB.CPU_STATE_IDLE]); } } return ticks; }
public static void sched_setaffinity(final BitSet affinity) { final CLibrary lib = CLibrary.INSTANCE; final cpu_set_t cpuset = new cpu_set_t(); final int size = version.isSameOrNewer(VERSION_2_6) ? cpu_set_t.SIZE_OF_CPU_SET_T : NativeLong.SIZE; final long[] bits = affinity.toLongArray(); for (int i = 0; i < bits.length; i++) { if (Platform.is64Bit()) { cpuset.__bits[i].setValue(bits[i]); } else { cpuset.__bits[i * 2].setValue(bits[i] & 0xFFFFFFFFL); cpuset.__bits[i * 2 + 1].setValue((bits[i] >>> 32) & 0xFFFFFFFFL); } } try { if (lib.sched_setaffinity(0, size, cpuset) != 0) { throw new IllegalStateException( "sched_setaffinity(0, " + size + ", 0x" + Utilities.toHexString(affinity) + ") failed; errno=" + Native.getLastError()); } } catch (LastErrorException e) { throw new IllegalStateException( "sched_setaffinity(0, " + size + ", 0x" + Utilities.toHexString(affinity) + ") failed; errno=" + e.getErrorCode(), e); } }
/** Updates logical and physical processor counts from sysctl calls */ private void calculateProcessorCounts() { IntByReference size = new IntByReference(SystemB.INT_SIZE); Pointer p = new Memory(size.getValue()); // Get number of logical processors if (0 != SystemB.INSTANCE.sysctlbyname("hw.logicalcpu", p, size, null, 0)) { LOG.error("Failed to get number of logical CPUs. Error code: " + Native.getLastError()); this.logicalProcessorCount = 1; } else this.logicalProcessorCount = p.getInt(0); // Get number of physical processors if (0 != SystemB.INSTANCE.sysctlbyname("hw.physicalcpu", p, size, null, 0)) { LOG.error("Failed to get number of physical CPUs. Error code: " + Native.getLastError()); this.physicalProcessorCount = 1; } else this.physicalProcessorCount = p.getInt(0); }
public static void tryMlockall() { int errno = Integer.MIN_VALUE; try { int result = CLibrary.mlockall(CLibrary.MCL_CURRENT); if (result != 0) { errno = Native.getLastError(); } else { LOCAL_MLOCKALL = true; } } catch (UnsatisfiedLinkError e) { // this will have already been logged by CLibrary, no need to repeat it return; } if (errno != Integer.MIN_VALUE) { if (errno == CLibrary.ENOMEM && System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("linux")) { logger.warn( "Unable to lock JVM memory (ENOMEM)." + " This can result in part of the JVM being swapped out." + " Increase RLIMIT_MEMLOCK (ulimit)."); } else if (!System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("mac")) { // OS X allows mlockall to be called, but always returns an error logger.warn("Unknown mlockall error " + errno); } } }
/** {@inheritDoc} */ @Override public String getName() { if (this.cpuName == null) { IntByReference size = new IntByReference(); if (0 != SystemB.INSTANCE.sysctlbyname("machdep.cpu.brand_string", null, size, null, 0)) { LOG.error("Failed to get Name. Error code: " + Native.getLastError()); return ""; } Pointer p = new Memory(size.getValue() + 1); if (0 != SystemB.INSTANCE.sysctlbyname("machdep.cpu.brand_string", p, size, null, 0)) { LOG.error("Failed to get Name. Error code: " + Native.getLastError()); return ""; } this.cpuName = p.getString(0); } return this.cpuName; }
public int GetClassLong(Pointer hWnd, GCFlags nIndex) throws Exception { int ret = u32.GetClassLongA(hWnd, nIndex.getValue()); if (ret == 0) { int err = Native.getLastError(); throw new Exception("GetClassLong failed. Error: " + err); } return ret; }
static void windowsImpl() { if (!Constants.WINDOWS) { throw new IllegalStateException( "bug: should not be trying to initialize ActiveProcessLimit for an unsupported OS"); } JNAKernel32Library lib = JNAKernel32Library.getInstance(); // create a new Job Pointer job = lib.CreateJobObjectW(null, null); if (job == null) { throw new UnsupportedOperationException("CreateJobObject: " + Native.getLastError()); } try { // retrieve the current basic limits of the job int clazz = JNAKernel32Library.JOBOBJECT_BASIC_LIMIT_INFORMATION_CLASS; JNAKernel32Library.JOBOBJECT_BASIC_LIMIT_INFORMATION limits = new JNAKernel32Library.JOBOBJECT_BASIC_LIMIT_INFORMATION(); limits.write(); if (!lib.QueryInformationJobObject(job, clazz, limits.getPointer(), limits.size(), null)) { throw new UnsupportedOperationException( "QueryInformationJobObject: " + Native.getLastError()); } limits.read(); // modify the number of active processes to be 1 (exactly the one process we will add to the // job). limits.ActiveProcessLimit = 1; limits.LimitFlags = JNAKernel32Library.JOB_OBJECT_LIMIT_ACTIVE_PROCESS; limits.write(); if (!lib.SetInformationJobObject(job, clazz, limits.getPointer(), limits.size())) { throw new UnsupportedOperationException( "SetInformationJobObject: " + Native.getLastError()); } // assign ourselves to the job if (!lib.AssignProcessToJobObject(job, lib.GetCurrentProcess())) { throw new UnsupportedOperationException( "AssignProcessToJobObject: " + Native.getLastError()); } } finally { lib.CloseHandle(job); } logger.debug("Windows ActiveProcessLimit initialization successful"); }
public PPROCESS_MEMORY_COUNTERS GetProcessMemoryInfo(Pointer Process) throws Exception { PPROCESS_MEMORY_COUNTERS ppsmemCounters = new PPROCESS_MEMORY_COUNTERS(); boolean success = psapi.GetProcessMemoryInfo(Process, ppsmemCounters, ppsmemCounters.size()); if (!success) { int err = Native.getLastError(); throw new Exception("GetProcessMemoryInfo failed. Error: " + err); } return ppsmemCounters; }
/* package */ HidDevice(String path, Frontend frontend) throws IOException { m_Frontend = frontend; udev udev = udev_new(); udev_device raw_dev = udev_device_new_from_syspath(udev, path); String dev_path = udev_device_get_devnode(raw_dev); udev_unref(udev); m_HidDeviceInfo = new HidDeviceInfo(path); // OPEN HERE // m_DeviceHandle = open(dev_path, O_RDWR); // If we have a good handle, return it. if (m_DeviceHandle <= 0) throw new IOException("open() failed, errno " + Native.getLastError()); // Get the report descriptor int[] desc_size = {0}; int res; hidraw_report_descriptor rpt_desc = new hidraw_report_descriptor(); // Get Report Descriptor Size res = ioctl(m_DeviceHandle, HIDIOCGRDESCSIZE, desc_size); if (res < 0) // FIXME ERROR HANDLING throw new IOException("ioctl(...HIDIOCGRDESCSIZE..) failed"); // perror("HIDIOCGRDESCSIZE"); // Get Report Descriptor rpt_desc.size = desc_size[0]; res = ioctl(m_DeviceHandle, HIDIOCGRDESC, rpt_desc); if (res < 0) throw new IOException("ioctl(...HIDIOCGRDESC..) failed"); // Determine if this device uses numbered reports. m_UsesNumberedReports = uses_numbered_reports(rpt_desc.value, rpt_desc.size); // --------------- // Magic here, assume that no HID device ever uses reports longer than 4kB m_InputReportBytes = new byte[4096 + 1]; m_OutputReportBytes = new byte[4096 + 1]; m_SyncStart = new SyncPoint(2); m_SyncShutdown = new SyncPoint(2); m_Thread = new Thread( new Runnable() { @Override public void run() { try { runReadOnBackground(); } catch (Exception e) { e.printStackTrace(); } } }, m_HidDeviceInfo.getPath()); m_Thread.start(); m_SyncStart.waitAndSync(); }
/** {@inheritDoc} */ @Override public long getSystemUptime() { IntByReference size = new IntByReference(); if (0 != SystemB.INSTANCE.sysctlbyname("kern.boottime", null, size, null, 0)) { LOG.error("Failed to get Boot Time. Error code: " + Native.getLastError()); return 0L; } // This should point to a 16-byte structure. If not, this code is valid if (size.getValue() != 16) throw new UnsupportedOperationException("sysctl kern.boottime should be 16 bytes but isn't."); Pointer p = new Memory(size.getValue() + 1); if (0 != SystemB.INSTANCE.sysctlbyname("kern.boottime", p, size, null, 0)) { LOG.error("Failed to get Boot Time. Error code: " + Native.getLastError()); return 0L; } // p now points to a 16-bit timeval structure for boot time. // First 8 bytes are seconds, second 8 bytes are microseconds (ignore) return System.currentTimeMillis() / 1000 - p.getLong(0); }
public LPMODULEINFO GetModuleInformation(Pointer hProcess, Pointer hModule) throws Exception { LPMODULEINFO lpmodinfo = new LPMODULEINFO(); boolean success = psapi.GetModuleInformation(hProcess, hModule, lpmodinfo, lpmodinfo.size()); if (!success) { int err = Native.getLastError(); throw new Exception("GetModuleInformation failed. Error: " + err); } return lpmodinfo; }
public void connect(SocketAddress endpoint, int timeout) throws IOException { try { int ret = connect(fd, sockaddr, sockaddr.size()); if (ret != 0) { throw new IOException(strerror(Native.getLastError())); } } catch (LastErrorException lee) { throw new IOException("native connect() failed : " + formatError(lee)); } is = new UnixSocketInputStream(); os = new UnixSocketOutputStream(); }
public static int syscall(int number, Object... args) { final CLibrary lib = CLibrary.INSTANCE; try { final int ret = lib.syscall(number, args); if (ret < 0) { throw new IllegalStateException("sched_getcpu() failed; errno=" + Native.getLastError()); } return ret; } catch (LastErrorException e) { throw new IllegalStateException("sched_getcpu() failed; errno=" + e.getErrorCode(), e); } }
public static int getpid() { final CLibrary lib = CLibrary.INSTANCE; try { final int ret = lib.getpid(); if (ret < 0) { throw new IllegalStateException("getpid() failed; errno=" + Native.getLastError()); } return ret; } catch (LastErrorException e) { throw new IllegalStateException("getpid() failed; errno=" + e.getErrorCode(), e); } }
/** {@inheritDoc} */ @Override public String getFamily() { if (this.cpuFamily == null) { IntByReference size = new IntByReference(SystemB.INT_SIZE); Pointer p = new Memory(size.getValue()); if (0 != SystemB.INSTANCE.sysctlbyname("machdep.cpu.family", p, size, null, 0)) { LOG.error("Failed to get Family. Error code: " + Native.getLastError()); return ""; } this.cpuFamily = Integer.toString(p.getInt(0)); } return this.cpuFamily; }
/** {@inheritDoc} */ @Override public boolean isCpu64bit() { if (this.cpu64 == null) { IntByReference size = new IntByReference(SystemB.INT_SIZE); Pointer p = new Memory(size.getValue()); if (0 != SystemB.INSTANCE.sysctlbyname("hw.cpu64bit_capable", p, size, null, 0)) { LOG.error("Failed to get 64Bit_capable. Error code: " + Native.getLastError()); return false; } this.cpu64 = p.getInt(0) != 0; } return this.cpu64.booleanValue(); }
public Pointer SendMessageTimeoutA( Pointer hWnd, Messages Msg, FType wParam, int lParam, int fuFlags, int uTimeout) throws Exception { PointerByReference lpdwResult = new PointerByReference(); int ret = u32.SendMessageTimeoutA( hWnd, Msg.getValue(), wParam.getValue(), lParam, fuFlags, uTimeout, lpdwResult); if (ret == 0) { int err = Native.getLastError(); throw new Exception("GetClassLong failed. Error: " + err); } return lpdwResult.getValue(); }
public static int sched_getcpu() { final CLibrary lib = CLibrary.INSTANCE; try { final int ret = lib.sched_getcpu(); if (ret < 0) { throw new IllegalStateException("sched_getcpu() failed; errno=" + Native.getLastError()); } return ret; } catch (LastErrorException e) { throw new IllegalStateException("sched_getcpu() failed; errno=" + e.getErrorCode(), e); } catch (UnsatisfiedLinkError ule) { try { final IntByReference cpu = new IntByReference(); final IntByReference node = new IntByReference(); final int ret = lib.syscall(318, cpu, node, null); if (ret != 0) { throw new IllegalStateException("getcpu() failed; errno=" + Native.getLastError()); } return cpu.getValue(); } catch (LastErrorException lee) { if (lee.getErrorCode() == 38 && Platform.is64Bit()) { // unknown call final Pointer getcpuAddr = new Pointer((-10L << 20) + 1024L * 2L); final Function getcpu = Function.getFunction(getcpuAddr, Function.C_CONVENTION); final IntByReference cpu = new IntByReference(); if (getcpu.invokeInt(new Object[] {cpu, null, null}) < 0) { throw new IllegalStateException("getcpu() failed; errno=" + Native.getLastError()); } else { return cpu.getValue(); } } else { throw new IllegalStateException("getcpu() failed; errno=" + lee.getErrorCode(), lee); } } } }
public List<Pointer> EnumProcessModules(Pointer hProcess) throws Exception { List<Pointer> list = new LinkedList<Pointer>(); Pointer[] lphModule = new Pointer[100 * 4]; IntByReference lpcbNeededs = new IntByReference(); boolean success = psapi.EnumProcessModules(hProcess, lphModule, lphModule.length, lpcbNeededs); if (!success) { int err = Native.getLastError(); throw new Exception("EnumProcessModules failed. Error: " + err); } for (int i = 0; i < lpcbNeededs.getValue() / 4; i++) { list.add(lphModule[i]); } return list; }
public static @NotNull cpu_set_t sched_getaffinity() { final CLibrary lib = CLibrary.INSTANCE; final cpu_set_t cpuset = new cpu_set_t(); final int size = version.isSameOrNewer(VERSION_2_6) ? cpu_set_t.SIZE_OF_CPU_SET_T : NativeLong.SIZE; try { if (lib.sched_getaffinity(0, size, cpuset) != 0) { throw new IllegalStateException( "sched_getaffinity(0, " + size + ", cpuset) failed; errno=" + Native.getLastError()); } } catch (LastErrorException e) { throw new IllegalStateException( "sched_getaffinity(0, (" + size + ") , cpuset) failed; errno=" + e.getErrorCode(), e); } return cpuset; }
static void bsdImpl() { boolean supported = Constants.FREE_BSD || OPENBSD || Constants.MAC_OS_X; if (supported == false) { throw new IllegalStateException( "bug: should not be trying to initialize RLIMIT_NPROC for an unsupported OS"); } JNACLibrary.Rlimit limit = new JNACLibrary.Rlimit(); limit.rlim_cur.setValue(0); limit.rlim_max.setValue(0); if (JNACLibrary.setrlimit(RLIMIT_NPROC, limit) != 0) { throw new UnsupportedOperationException( "RLIMIT_NPROC unavailable: " + JNACLibrary.strerror(Native.getLastError())); } logger.debug("BSD RLIMIT_NPROC initialization successful"); }
public List<Integer> enumProcesses() throws Exception { List<Integer> list = new LinkedList<Integer>(); int[] pProcessIds = new int[256]; IntByReference pBytesReturned = new IntByReference(); boolean success = psapi.EnumProcesses(pProcessIds, pProcessIds.length * Integer.SIZE / 8, pBytesReturned); if (!success) { int err = Native.getLastError(); throw new Exception("EnumProcesses failed. Error: " + err); } int size = (pBytesReturned.getValue() / (Integer.SIZE / 8)); for (int i = 0; i < size; i++) list.add(pProcessIds[i]); return list; }
/** {@inheritDoc} */ @Override public long[] getSystemCpuLoadTicks() { long[] ticks = new long[curTicks.length]; int machPort = SystemB.INSTANCE.mach_host_self(); HostCpuLoadInfo cpuLoadInfo = new HostCpuLoadInfo(); if (0 != SystemB.INSTANCE.host_statistics( machPort, SystemB.HOST_CPU_LOAD_INFO, cpuLoadInfo, new IntByReference(cpuLoadInfo.size()))) { LOG.error("Failed to get System CPU ticks. Error code: " + Native.getLastError()); return ticks; } // Switch order to match linux ticks[0] = cpuLoadInfo.cpu_ticks[SystemB.CPU_STATE_USER]; ticks[1] = cpuLoadInfo.cpu_ticks[SystemB.CPU_STATE_NICE]; ticks[2] = cpuLoadInfo.cpu_ticks[SystemB.CPU_STATE_SYSTEM]; ticks[3] = cpuLoadInfo.cpu_ticks[SystemB.CPU_STATE_IDLE]; return ticks; }
static void solarisImpl() { // first be defensive: we can give nice errors this way, at the very least. boolean supported = Constants.SUN_OS; if (supported == false) { throw new IllegalStateException( "bug: should not be trying to initialize priv_set for an unsupported OS"); } // we couldn't link methods, could be some really ancient Solaris or some bug if (libc_solaris == null) { throw new UnsupportedOperationException( "priv_set unavailable: could not link methods. requires Solaris 10+"); } // drop a null-terminated list of privileges if (libc_solaris.priv_set(PRIV_OFF, PRIV_ALLSETS, PRIV_PROC_FORK, PRIV_PROC_EXEC, null) != 0) { throw new UnsupportedOperationException( "priv_set unavailable: priv_set(): " + JNACLibrary.strerror(Native.getLastError())); } logger.debug("Solaris priv_set initialization successful"); }
/** try to install our BPF filters via seccomp() or prctl() to block execution */ private static int linuxImpl() { // first be defensive: we can give nice errors this way, at the very least. // also, some of these security features get backported to old versions, checking kernel version // here is a big no-no! final Arch arch = ARCHITECTURES.get(Constants.OS_ARCH); boolean supported = Constants.LINUX && arch != null; if (supported == false) { throw new UnsupportedOperationException( "seccomp unavailable: '" + Constants.OS_ARCH + "' architecture unsupported"); } // we couldn't link methods, could be some really ancient kernel (e.g. < 2.1.57) or some bug if (linux_libc == null) { throw new UnsupportedOperationException( "seccomp unavailable: could not link methods. requires kernel 3.5+ with CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER compiled in"); } // pure paranoia: // check that unimplemented syscalls actually return ENOSYS // you never know (e.g. https://code.google.com/p/chromium/issues/detail?id=439795) if (linux_syscall(999) >= 0 || Native.getLastError() != ENOSYS) { throw new UnsupportedOperationException( "seccomp unavailable: your kernel is buggy and you should upgrade"); } // try to check system calls really are who they claim // you never know (e.g. // https://chromium.googlesource.com/chromium/src.git/+/master/sandbox/linux/seccomp-bpf/sandbox_bpf.cc#57) final int bogusArg = 0xf7a46a5c; // test seccomp(BOGUS) long ret = linux_syscall(arch.seccomp, bogusArg); if (ret != -1) { throw new UnsupportedOperationException( "seccomp unavailable: seccomp(BOGUS_OPERATION) returned " + ret); } else { int errno = Native.getLastError(); switch (errno) { case ENOSYS: break; // ok case EINVAL: break; // ok default: throw new UnsupportedOperationException( "seccomp(BOGUS_OPERATION): " + JNACLibrary.strerror(errno)); } } // test seccomp(VALID, BOGUS) ret = linux_syscall(arch.seccomp, SECCOMP_SET_MODE_FILTER, bogusArg); if (ret != -1) { throw new UnsupportedOperationException( "seccomp unavailable: seccomp(SECCOMP_SET_MODE_FILTER, BOGUS_FLAG) returned " + ret); } else { int errno = Native.getLastError(); switch (errno) { case ENOSYS: break; // ok case EINVAL: break; // ok default: throw new UnsupportedOperationException( "seccomp(SECCOMP_SET_MODE_FILTER, BOGUS_FLAG): " + JNACLibrary.strerror(errno)); } } // test prctl(BOGUS) ret = linux_prctl(bogusArg, 0, 0, 0, 0); if (ret != -1) { throw new UnsupportedOperationException( "seccomp unavailable: prctl(BOGUS_OPTION) returned " + ret); } else { int errno = Native.getLastError(); switch (errno) { case ENOSYS: break; // ok case EINVAL: break; // ok default: throw new UnsupportedOperationException( "prctl(BOGUS_OPTION): " + JNACLibrary.strerror(errno)); } } // now just normal defensive checks // check for GET_NO_NEW_PRIVS switch (linux_prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0)) { case 0: break; // not yet set case 1: break; // already set by caller default: int errno = Native.getLastError(); if (errno == EINVAL) { // friendly error, this will be the typical case for an old kernel throw new UnsupportedOperationException( "seccomp unavailable: requires kernel 3.5+ with CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER compiled in"); } else { throw new UnsupportedOperationException( "prctl(PR_GET_NO_NEW_PRIVS): " + JNACLibrary.strerror(errno)); } } // check for SECCOMP switch (linux_prctl(PR_GET_SECCOMP, 0, 0, 0, 0)) { case 0: break; // not yet set case 2: break; // already in filter mode by caller default: int errno = Native.getLastError(); if (errno == EINVAL) { throw new UnsupportedOperationException( "seccomp unavailable: CONFIG_SECCOMP not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed"); } else { throw new UnsupportedOperationException( "prctl(PR_GET_SECCOMP): " + JNACLibrary.strerror(errno)); } } // check for SECCOMP_MODE_FILTER if (linux_prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, 0, 0, 0) != 0) { int errno = Native.getLastError(); switch (errno) { case EFAULT: break; // available case EINVAL: throw new UnsupportedOperationException( "seccomp unavailable: CONFIG_SECCOMP_FILTER not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed"); default: throw new UnsupportedOperationException( "prctl(PR_SET_SECCOMP): " + JNACLibrary.strerror(errno)); } } // ok, now set PR_SET_NO_NEW_PRIVS, needed to be able to set a seccomp filter as ordinary user if (linux_prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) { throw new UnsupportedOperationException( "prctl(PR_SET_NO_NEW_PRIVS): " + JNACLibrary.strerror(Native.getLastError())); } // check it worked if (linux_prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) != 1) { throw new UnsupportedOperationException( "seccomp filter did not really succeed: prctl(PR_GET_NO_NEW_PRIVS): " + JNACLibrary.strerror(Native.getLastError())); } // BPF installed to check arch, limit, then syscall. See // https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt for details. SockFilter insns[] = { /* 1 */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, SECCOMP_DATA_ARCH_OFFSET), // /* 2 */ BPF_JUMP( BPF_JMP + BPF_JEQ + BPF_K, arch.audit, 0, 7), // if (arch != audit) goto fail; /* 3 */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, SECCOMP_DATA_NR_OFFSET), // /* 4 */ BPF_JUMP( BPF_JMP + BPF_JGT + BPF_K, arch.limit, 5, 0), // if (syscall > LIMIT) goto fail; /* 5 */ BPF_JUMP( BPF_JMP + BPF_JEQ + BPF_K, arch.fork, 4, 0), // if (syscall == FORK) goto fail; /* 6 */ BPF_JUMP( BPF_JMP + BPF_JEQ + BPF_K, arch.vfork, 3, 0), // if (syscall == VFORK) goto fail; /* 7 */ BPF_JUMP( BPF_JMP + BPF_JEQ + BPF_K, arch.execve, 2, 0), // if (syscall == EXECVE) goto fail; /* 8 */ BPF_JUMP( BPF_JMP + BPF_JEQ + BPF_K, arch.execveat, 1, 0), // if (syscall == EXECVEAT) goto fail; /* 9 */ BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW), // pass: return OK; /* 10 */ BPF_STMT( BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (EACCES & SECCOMP_RET_DATA)), // fail: return EACCES; }; // seccomp takes a long, so we pass it one explicitly to keep the JNA simple SockFProg prog = new SockFProg(insns); prog.write(); long pointer = Pointer.nativeValue(prog.getPointer()); int method = 1; // install filter, if this works, after this there is no going back! // first try it with seccomp(SECCOMP_SET_MODE_FILTER), falling back to prctl() if (linux_syscall( arch.seccomp, SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, new NativeLong(pointer)) != 0) { method = 0; int errno1 = Native.getLastError(); if (logger.isDebugEnabled()) { logger.debug( "seccomp(SECCOMP_SET_MODE_FILTER): " + JNACLibrary.strerror(errno1) + ", falling back to prctl(PR_SET_SECCOMP)..."); } if (linux_prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, pointer, 0, 0) != 0) { int errno2 = Native.getLastError(); throw new UnsupportedOperationException( "seccomp(SECCOMP_SET_MODE_FILTER): " + JNACLibrary.strerror(errno1) + ", prctl(PR_SET_SECCOMP): " + JNACLibrary.strerror(errno2)); } } // now check that the filter was really installed, we should be in filter mode. if (linux_prctl(PR_GET_SECCOMP, 0, 0, 0, 0) != 2) { throw new UnsupportedOperationException( "seccomp filter installation did not really succeed. seccomp(PR_GET_SECCOMP): " + JNACLibrary.strerror(Native.getLastError())); } logger.debug( "Linux seccomp filter installation successful, threads: [{}]", method == 1 ? "all" : "app"); return method; }
@JRubyMethod( name = {"error"}, meta = true) public static final IRubyObject error(ThreadContext context, IRubyObject recv) { return context.getRuntime().newFixnum(Native.getLastError()); }
public int errno() { return Native.getLastError(); }
public String getLastError() { return strerror(Native.getLastError()); }