/*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* For more information, please refer to <http://unlicense.org/>
*/
package jxtn.core.unix;
import sun.misc.Unsafe;
/**
* {@code prctl()} syscall wrappers
*
* @author aqd
*/
public final class NativePrctl extends JNIBase {
public static final int PR_SET_PDEATHSIG = 1;
public static final int PR_GET_PDEATHSIG = 2;
/* Get/set current->mm->dumpable */
public static final int PR_GET_DUMPABLE = 3;
public static final int PR_SET_DUMPABLE = 4;
/* Get/set unaligned access control bits (if meaningful) */
public static final int PR_GET_UNALIGN = 5;
public static final int PR_SET_UNALIGN = 6;
public static final int PR_UNALIGN_NOPRINT = 1;
public static final int PR_UNALIGN_SIGBUS = 2;
/* Get/set whether or not to drop capabilities on setuid() away from
* uid 0 (as per security/commoncap.c) */
public static final int PR_GET_KEEPCAPS = 7;
public static final int PR_SET_KEEPCAPS = 8;
/* Get/set floating-point emulation control bits (if meaningful) */
public static final int PR_GET_FPEMU = 9;
public static final int PR_SET_FPEMU = 10;
public static final int PR_FPEMU_NOPRINT = 1;
public static final int PR_FPEMU_SIGFPE = 2;
/* Get/set floating-point exception mode (if meaningful) */
public static final int PR_GET_FPEXC = 11;
public static final int PR_SET_FPEXC = 12;
public static final int PR_FP_EXC_SW_ENABLE = 0;
public static final int PR_FP_EXC_DIV = 0;
public static final int PR_FP_EXC_OVF = 0;
public static final int PR_FP_EXC_UND = 0;
public static final int PR_FP_EXC_RES = 0;
public static final int PR_FP_EXC_INV = 0;
public static final int PR_FP_EXC_DISABLED = 0;
public static final int PR_FP_EXC_NONRECOV = 1;
public static final int PR_FP_EXC_ASYNC = 2;
public static final int PR_FP_EXC_PRECISE = 3;
/* Get/set whether we use statistical process timing or accurate timestamp
* based process timing */
public static final int PR_GET_TIMING = 13;
public static final int PR_SET_TIMING = 14;
public static final int PR_TIMING_STATISTICAL = 0; /* Normal, traditional, statistical process timing */
public static final int PR_TIMING_TIMESTAMP = 1; /* Accurate timestamp based process timing */
public static final int PR_SET_NAME = 15;
public static final int PR_GET_NAME = 16;
/* Get/set process endian */
public static final int PR_GET_ENDIAN = 19;
public static final int PR_SET_ENDIAN = 20;
public static final int PR_ENDIAN_BIG = 0;
public static final int PR_ENDIAN_LITTLE = 1;
public static final int PR_ENDIAN_PPC_LITTLE = 2;
/* Get/set process seccomp mode */
public static final int PR_GET_SECCOMP = 21;
public static final int PR_SET_SECCOMP = 22;
/* Get/set the capability bounding set (as per security/commoncap.c) */
public static final int PR_CAPBSET_READ = 23;
public static final int PR_CAPBSET_DROP = 24;
/* Get/set the process' ability to use the timestamp counter instruction */
public static final int PR_GET_TSC = 25;
public static final int PR_SET_TSC = 26;
public static final int PR_TSC_ENABLE = 1;
public static final int PR_TSC_SIGSEGV = 2;
/* Get/set securebits (as per security/commoncap.c) */
public static final int PR_GET_SECUREBITS = 27;
public static final int PR_SET_SECUREBITS = 28;
/*
* Get/set the timerslack as used by poll/select/nanosleep
* A value of 0 means "use default"
*/
public static final int PR_SET_TIMERSLACK = 29;
public static final int PR_GET_TIMERSLACK = 30;
public static final int PR_TASK_PERF_EVENTS_DISABLE = 31;
public static final int PR_TASK_PERF_EVENTS_ENABLE = 32;
/*
* Set early/late kill mode for hwpoison memory corruption.
* This influences when the process gets killed on a memory corruption.
*/
public static final int PR_MCE_KILL = 33;
public static final int PR_MCE_KILL_CLEAR = 0;
public static final int PR_MCE_KILL_SET = 1;
public static final int PR_MCE_KILL_LATE = 0;
public static final int PR_MCE_KILL_EARLY = 1;
public static final int PR_MCE_KILL_DEFAULT = 2;
public static final int PR_MCE_KILL_GET = 34;
/*
* Tune up process memory map specifics.
*/
public static final int PR_SET_MM = 35;
public static final int PR_SET_MM_START_CODE = 1;
public static final int PR_SET_MM_END_CODE = 2;
public static final int PR_SET_MM_START_DATA = 3;
public static final int PR_SET_MM_END_DATA = 4;
public static final int PR_SET_MM_START_STACK = 5;
public static final int PR_SET_MM_START_BRK = 6;
public static final int PR_SET_MM_BRK = 7;
public static final int PR_SET_MM_ARG_START = 8;
public static final int PR_SET_MM_ARG_END = 9;
public static final int PR_SET_MM_ENV_START = 10;
public static final int PR_SET_MM_ENV_END = 11;
public static final int PR_SET_MM_AUXV = 12;
public static final int PR_SET_MM_EXE_FILE = 13;
public static final int PR_SET_MM_MAP = 14;
public static final int PR_SET_MM_MAP_SIZE = 15;
/*
* This structure provides new memory descriptor
* map which mostly modifies /proc/pid/stat[m]
* output for a task. This mostly done in a
* sake of checkpoint/restore functionality.
*/
// struct prctl_mm_map
// {
// __u64 start_code; /* code section bounds */
// __u64 end_code;
// __u64 start_data; /* data section bounds */
// __u64 end_data;
// __u64 start_brk; /* heap for brk() syscall */
// __u64 brk;
// __u64 start_stack; /* stack starts at */
// __u64 arg_start; /* command line arguments bounds */
// __u64 arg_end;
// __u64 env_start; /* environment variables bounds */
// __u64 env_end;
// __u64 *auxv; /* auxiliary vector */
// __u32 auxv_size; /* vector size */
// __u32 exe_fd; /* /proc/$pid/exe link file */
// };
/*
* Set specific pid that is allowed to ptrace the current task.
* A value of 0 mean "no process".
*/
public static final int PR_SET_PTRACER = 0;
public static final long PR_SET_PTRACER_ANY = -1L;
public static final int PR_SET_CHILD_SUBREAPER = 36;
public static final int PR_GET_CHILD_SUBREAPER = 37;
/*
* If no_new_privs is set, then operations that grant new privileges (i.e.
* execve) will either fail or not grant them. This affects suid/sgid,
* file capabilities, and LSMs.
*
* Operations that merely manipulate or drop existing privileges (setresuid,
* capset, etc.) will still work. Drop those privileges if you want them gone.
*
* Changing LSM security domain is considered a new privilege. So, for example,
* asking selinux for a specific new context (e.g. with runcon) will result
* in execve returning -EPERM.
*
* See Documentation/prctl/no_new_privs.txt for more details.
*/
public static final int PR_SET_NO_NEW_PRIVS = 38;
public static final int PR_GET_NO_NEW_PRIVS = 39;
public static final int PR_GET_TID_ADDRESS = 40;
public static final int PR_SET_THP_DISABLE = 41;
public static final int PR_GET_THP_DISABLE = 42;
/*
* Tell the kernel to start/stop helping userspace manage bounds tables.
*/
public static final int PR_MPX_ENABLE_MANAGEMENT = 43;
public static final int PR_MPX_DISABLE_MANAGEMENT = 44;
public static final int PR_SET_FP_MODE = 45;
public static final int PR_GET_FP_MODE = 46;
public static final int PR_FP_MODE_FR = (1 << 0); /* 64b FP registers */
public static final int PR_FP_MODE_FRE = (1 << 1); /* 32b compatibility */
/* Control the ambient capability set */
public static final int PR_CAP_AMBIENT = 47;
public static final int PR_CAP_AMBIENT_IS_SET = 1;
public static final int PR_CAP_AMBIENT_RAISE = 2;
public static final int PR_CAP_AMBIENT_LOWER = 3;
public static final int PR_CAP_AMBIENT_CLEAR_ALL = 4;
/**
* Get the thread name
* <p>
* <b>NOT</b> process name, because none of Java threads is the root thread
* </p>
*
* @return thread name
*/
public static String prGetName() {
final int NAME_LEN = 16;
Unsafe unsafe = Memory.unsafe;
long cbuffer = unsafe.allocateMemory(NAME_LEN);
try {
if (prctl(PR_GET_NAME, cbuffer, 0L, 0L, 0L) == -1) {
System.err.println("PR_GET_NAME: " + NativeErrno.errName());
return null;
}
byte[] jbuffer = new byte[NAME_LEN];
unsafe.copyMemory(null, cbuffer, jbuffer, Unsafe.ARRAY_BYTE_BASE_OFFSET, jbuffer.length);
return CStrings.toString(jbuffer);
} finally {
unsafe.freeMemory(cbuffer);
}
}
/**
* Set the thread name
* <p>
* <b>NOT</b> process name, because none of Java threads is the root thread
* </p>
*
* @param name thread name
* @return true on success
*/
public static boolean prSetName(String name) {
final int NAME_LEN = 16;
Unsafe unsafe = Memory.unsafe;
long cbuffer = unsafe.allocateMemory(NAME_LEN);
try {
byte[] jbuffer = CStrings.from(name, NAME_LEN);
unsafe.copyMemory(jbuffer, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, cbuffer, jbuffer.length);
if (prctl(PR_SET_NAME, cbuffer, 0L, 0L, 0L) == -1) {
System.err.println("PR_SET_NAME: " + NativeErrno.errName());
return false;
}
return true;
} finally {
unsafe.freeMemory(cbuffer);
}
}
private static native int prctl(int option, long arg2, long arg3, long arg4, long arg5);
private NativePrctl() {
}
}