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}