Esempio n. 1
1
  /** {@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);
   }
 }
Esempio n. 3
0
  /** 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);
  }
Esempio n. 4
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);
      }
    }
  }
Esempio n. 5
0
 /** {@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;
 }
Esempio n. 6
0
 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;
 }
Esempio n. 7
0
  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");
  }
Esempio n. 8
0
 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;
 }
Esempio n. 9
0
  /* 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();
  }
Esempio n. 10
0
 /** {@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);
 }
Esempio n. 11
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);
   }
 }
Esempio n. 15
0
 /** {@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;
 }
Esempio n. 16
0
 /** {@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();
 }
Esempio n. 17
0
 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);
        }
      }
    }
  }
Esempio n. 19
0
  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;
  }
Esempio n. 21
0
  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");
  }
Esempio n. 22
0
  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;
  }
Esempio n. 23
0
 /** {@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;
 }
Esempio n. 24
0
  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");
  }
Esempio n. 25
0
  /** 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;
  }
Esempio n. 26
0
 @JRubyMethod(
     name = {"error"},
     meta = true)
 public static final IRubyObject error(ThreadContext context, IRubyObject recv) {
   return context.getRuntime().newFixnum(Native.getLastError());
 }
Esempio n. 27
0
 public int errno() {
   return Native.getLastError();
 }
Esempio n. 28
0
 public String getLastError() {
   return strerror(Native.getLastError());
 }