linux_personality/lib.rs
1#![cfg(target_os = "linux")]
2//! # linux-personality
3//!
4//! This crate is a type safe wrapper around Linux `personality` function.
5//!
6//! # Examples
7//! This sets the personality.
8//!
9//! ```rust
10//! extern crate linux_personality;
11//! use linux_personality::personality;
12//! use linux_personality::Personality;
13//!
14//! let previous_personality = personality(Personality::PER_LINUX).unwrap();
15//! ```
16//!
17//! This gets the personality.
18//!
19//! ```rust
20//! extern crate linux_personality;
21//! use linux_personality::get_personality;
22//!
23//! let persona = get_personality().unwrap();
24//! ```
25
26extern crate libc;
27#[macro_use]
28extern crate bitflags;
29
30bitflags! {
31 pub struct Personality: u32 {
32 /// Have [uname(2)][uname2] report a 2.6.40+ version number rather than
33 /// a 3.x version number. Added as a stopgap measure to support broken
34 /// applications that could not handle the kernel version- numbering
35 /// switch from 2.6.x to 3.x.
36 ///
37 /// [uname2]: http://man7.org/linux/man-pages/man2/uname.2.html
38 const UNAME26 = 0x0020000;
39
40 /// With this flag set, disable address-space-layout randomization.
41 const ADDR_NO_RANDOMIZE = 0x0040000;
42
43 /// User-space function pointers to signal handlers point (on certain
44 /// architectures) to descriptors.
45 const FDPIC_FUNCPTRS = 0x0080000;
46
47 /// Map page 0 as read-only (to support binaries that depend on this
48 /// SVr4 behavior).
49 const MMAP_PAGE_ZERO = 0x0100000;
50
51 /// With this flag set, provide legacy virtual address space layout.
52 const ADDR_COMPAT_LAYOUT = 0x0200000;
53
54 /// With this flag set, `PROT_READ` implies `PROT_EXEC` for
55 /// [`mmap(2)`](http://man7.org/linux/man-pages/man2/mmap.2.html).
56 const READ_IMPLIES_EXEC = 0x0400000;
57
58 /// Limit the address space to 32 bits.
59 const ADDR_LIMIT_32BIT = 0x0800000;
60
61 /// No effects(?).
62 const SHORT_INODE = 0x1000000;
63
64 /// No effects(?).
65 const WHOLE_SECONDS = 0x2000000;
66
67 /// With this flag set, [`select(2)`][select2],
68 /// [`pselect(2)`][pselect2], and [`ppoll(2)`][ppoll2] do not modify the
69 /// returned timeout argument when interrupted by a signal handler.
70 ///
71 /// [select2]: http://man7.org/linux/man-pages/man2/select.2.html
72 /// [pselect2]: http://man7.org/linux/man-pages/man2/pselect.2.html
73 /// [ppoll2]: http://man7.org/linux/man-pages/man2/ppoll.2.html
74 const STICKY_TIMEOUTS = 0x4000000;
75
76 /// With this flag set, use `0xC0000000` as the offset at which to
77 /// search a virtual memory chunk on [`mmap(2)`][mmap2]; otherwise use
78 /// `0xFFFFE000`.
79 ///
80 /// [mmap2]: http://man7.org/linux/man-pages/man2/mmap.2.html
81 const ADDR_LIMIT_3GB = 0x8000000;
82
83 /// Linux
84 const PER_LINUX = 0x0000;
85
86 /// Implies `ADDR_LIMIT_32BIT`
87 const PER_LINUX_32BIT = 0x0000 | Self::ADDR_LIMIT_32BIT.bits();
88
89 /// Implies `FDPIC_FUNCPTRS`.
90 const PER_LINUX_FDPIC = 0x0000 | Self::FDPIC_FUNCPTRS.bits();
91
92 /// Implies `STICKY_TIMEOUTS` and `MMAP_PAGE_ZERO`; otherwise no
93 /// effects.
94 const PER_SVR4 = 0x0001 | Self::STICKY_TIMEOUTS.bits() | Self::MMAP_PAGE_ZERO.bits();
95
96 /// Implies `STICKY_TIMEOUTS` and `SHORT_INODE`; otherwise no effects.
97 const PER_SVR3 = 0x0002 | Self::STICKY_TIMEOUTS.bits() | Self::SHORT_INODE.bits();
98
99 /// Implies `STICKY_TIMEOUTS`, `WHOLE_SECONDS`, and `SHORT_INODE`;
100 /// otherwise no effects.
101 const PER_SCOSVR3 = 0x0003 | Self::STICKY_TIMEOUTS.bits() | Self::WHOLE_SECONDS.bits() | Self::SHORT_INODE.bits();
102
103 /// Implies `STICKY_TIMEOUTS` and `WHOLE_SECONDS`; otherwise no
104 /// effects.
105 const PER_OSR5 = 0x0003 | Self::STICKY_TIMEOUTS.bits() | Self::WHOLE_SECONDS.bits();
106
107 /// Implies `STICKY_TIMEOUTS` and `SHORT_INODE`; otherwise no effects.
108 const PER_WYSEV386 = 0x0004 | Self::STICKY_TIMEOUTS.bits() | Self::SHORT_INODE.bits();
109
110 /// Implies STICKY_TIMEOUTS; otherwise no effects.
111 const PER_ISCR4 = 0x0005 | Self::STICKY_TIMEOUTS.bits();
112
113 /// BSD. (No effects.)
114 const PER_BSD = 0x0006;
115
116 /// Implies `STICKY_TIMEOUTS`. Divert library and dynamic linker
117 /// searches to `/usr/gnemul`. Buggy, largely unmaintained, and almost
118 /// entirely unused; support was removed in Linux 2.6.26.
119 const PER_SUNOS = 0x0006 | Self::STICKY_TIMEOUTS.bits();
120
121 /// Implies `STICKY_TIMEOUTS` and `SHORT_INODE`; otherwise no effects.
122 const PER_XENIX = 0x0007 | Self::STICKY_TIMEOUTS.bits() | Self::SHORT_INODE.bits();
123
124 /// [To be documented.]
125 const PER_LINUX32 = 0x0008;
126
127 /// Implies ADDR_LIMIT_3GB.
128 const PER_LINUX32_3GB = 0x0008 | Self::ADDR_LIMIT_3GB.bits();
129
130 /// IRIX 5 32-bit. Never fully functional; support dropped in Linux
131 /// 2.6.27. Implies `STICKY_TIMEOUTS`.
132 const PER_IRIX32 = 0x0009 | Self::STICKY_TIMEOUTS.bits();
133
134 /// IRIX 6 new 32-bit. Implies `STICKY_TIMEOUTS`; otherwise no effects.
135 const PER_IRIXN32 = 0x000a | Self::STICKY_TIMEOUTS.bits();
136
137 /// IRIX 6 64-bit. Implies `STICKY_TIMEOUTS`; otherwise no effects.
138 const PER_IRIX64 = 0x000b | Self::STICKY_TIMEOUTS.bits();
139
140 /// [To be documented.]
141 const PER_RISCOS = 0x000c;
142
143 /// Implies `STICKY_TIMEOUTS`; otherwise no effects.
144 const PER_SOLARIS = 0x000d | Self::STICKY_TIMEOUTS.bits();
145
146 /// Implies `STICKY_TIMEOUTS` and `MMAP_PAGE_ZERO`; otherwise no effects.
147 const PER_UW7 = 0x000e | Self::STICKY_TIMEOUTS.bits() | Self::MMAP_PAGE_ZERO.bits();
148
149 /// OSF/1 v4. On alpha, clear top 32 bits of iov_len in the user's
150 /// buffer for compatibility with old versions of OSF/1 where iov_len
151 /// was defined as. int.
152 const PER_OSF4 = 0x000f;
153
154 /// Support for 32-bit HP/UX. This support was never complete, and was
155 /// dropped so that since Linux 4.0, this value has no effect.
156 const PER_HPUX = 0x0010;
157
158 /// [to be documented]
159 const PER_MASK = 0x00ff;
160 }
161}
162
163/// Set the process domain execution model.
164///
165/// # Return value
166/// On success returns the Previous `persona` is returned.
167/// On failure returns `Err(())` if the kernel was unable to change personality.
168pub fn personality(persona: Personality) -> Result<Personality, ()> {
169 let previous_persona = unsafe { libc::personality(persona.bits() as libc::c_ulong) };
170 if previous_persona == -1 {
171 Err(())
172 } else {
173 Ok(Personality::from_bits(previous_persona as u32).unwrap())
174 }
175}
176
177/// This function only gets the current `persona`.
178///
179/// # Return value
180/// On success returns the Previous `persona` is returned.
181/// On failure returns `Err(())` if the kernel was unable to retrieve personality.
182pub fn get_personality() -> Result<Personality, ()> {
183 let persona = unsafe { libc::personality(0xffffffff as libc::c_ulong) };
184 if persona == -1 {
185 Err(())
186 } else {
187 Ok(Personality::from_bits(persona as u32).unwrap())
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 #[test]
194 fn test_linux_per() {
195 use super::personality;
196 use super::Personality;
197
198 personality(Personality::PER_LINUX).unwrap();
199 }
200
201 #[test]
202 fn retrieve_per() {
203 use super::get_personality;
204
205 get_personality().unwrap();
206 }
207}