Skip to content

Commit d03be06

Browse files
committed
api: add an unsafe API for creating keys from IDs
1 parent 64c41c0 commit d03be06

File tree

1 file changed

+46
-30
lines changed

1 file changed

+46
-30
lines changed

src/api.rs

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,16 @@ pub struct Keyring {
7575
}
7676

7777
impl Keyring {
78-
fn new(id: KeyringSerial) -> Self {
78+
/// Instantiate a keyring from an ID.
79+
///
80+
/// This is unsafe because no keyring is known to exist with the given ID.
81+
pub unsafe fn new(id: KeyringSerial) -> Self {
82+
Keyring {
83+
id: id,
84+
}
85+
}
86+
87+
fn new_impl(id: KeyringSerial) -> Self {
7988
Keyring {
8089
id: id,
8190
}
@@ -99,7 +108,7 @@ impl Keyring {
99108
pub fn request<D>(description: D) -> Result<Self>
100109
where D: AsRef<str>,
101110
{
102-
Keyring::new(0).request_keyring(description)
111+
Keyring::new_impl(0).request_keyring(description)
103112
}
104113

105114
/// Requests a keyring with the given description by searching the thread, process, and session
@@ -111,12 +120,12 @@ impl Keyring {
111120
where D: AsRef<str>,
112121
I: AsRef<str>,
113122
{
114-
Keyring::new(0).request_keyring_with_fallback(description, info)
123+
Keyring::new_impl(0).request_keyring_with_fallback(description, info)
115124
}
116125

117126
fn get_keyring(id: SpecialKeyring, create: bool) -> Result<Keyring> {
118127
let res = unsafe { keyctl_get_keyring_ID(id.serial(), create as libc::c_int) };
119-
check_call(res as libc::c_long, Keyring::new(res))
128+
check_call(res as libc::c_long, Keyring::new_impl(res))
120129
}
121130

122131
/// Attach to a special keyring. Fails if the keyring does not already exist.
@@ -132,7 +141,7 @@ impl Keyring {
132141
/// Create a new anonymous keyring and set it as the session keyring.
133142
pub fn join_anonymous_session() -> Result<Self> {
134143
let res = unsafe { keyctl_join_session_keyring(ptr::null()) };
135-
check_call(res as libc::c_long, Keyring::new(res))
144+
check_call(res as libc::c_long, Keyring::new_impl(res))
136145
}
137146

138147
/// Attached to a named session keyring.
@@ -144,7 +153,7 @@ impl Keyring {
144153
{
145154
let name_cstr = CString::new(name.as_ref()).unwrap();
146155
let res = unsafe { keyctl_join_session_keyring(name_cstr.as_ptr()) };
147-
check_call(res as libc::c_long, Keyring::new(res))
156+
check_call(res as libc::c_long, Keyring::new_impl(res))
148157
}
149158

150159
/// Clears the contents of the keyring.
@@ -201,7 +210,7 @@ impl Keyring {
201210
where D: AsRef<str>,
202211
{
203212
let res = self.search_impl("user", description.as_ref())?;
204-
check_call(res, Key::new(res as key_serial_t))
213+
check_call(res, Key::new_impl(res as key_serial_t))
205214
}
206215

207216
/// Recursively search the keyring for a keyring with the matching description.
@@ -214,7 +223,7 @@ impl Keyring {
214223
where D: AsRef<str>,
215224
{
216225
let res = self.search_impl("keyring", description.as_ref())?;
217-
check_call(res, Keyring::new(res as key_serial_t))
226+
check_call(res, Keyring::new_impl(res as key_serial_t))
218227
}
219228

220229
/// Return all immediate children of the keyring.
@@ -231,12 +240,12 @@ impl Keyring {
231240
})?;
232241
unsafe { buffer.set_len((actual_sz as usize) / mem::size_of::<KeyringSerial>()) };
233242
let keys = buffer.iter()
234-
.map(|&id| Key::new(id))
243+
.map(|&id| Key::new_impl(id))
235244
.partition(|key| key.description().unwrap().type_ == "keyring");
236245
Ok((keys.1,
237246
keys.0
238247
.iter()
239-
.map(|key| Keyring::new(key.id))
248+
.map(|key| Keyring::new_impl(key.id))
240249
.collect::<Vec<_>>()))
241250
}
242251

@@ -245,7 +254,7 @@ impl Keyring {
245254
/// If one does not exist, it will be created. Requires `write` permission on the keyring.
246255
pub fn attach_persistent(&mut self) -> Result<Self> {
247256
let res = unsafe { keyctl_get_persistent(!0, self.id) };
248-
check_call(res, Keyring::new(res as key_serial_t))
257+
check_call(res, Keyring::new_impl(res as key_serial_t))
249258
}
250259

251260
/// Adds a key of a specific type to the keyring.
@@ -276,7 +285,7 @@ impl Keyring {
276285
payload.len(),
277286
self.id)
278287
};
279-
check_call(res as libc::c_long, Key::new(res))
288+
check_call(res as libc::c_long, Key::new_impl(res))
280289
}
281290

282291
/// Adds a keyring to the current keyring.
@@ -287,7 +296,7 @@ impl Keyring {
287296
where D: Borrow<<keytypes::Keyring as KeyType>::Description>,
288297
{
289298
let key = self.add_key::<keytypes::Keyring, _, _>(description, ())?;
290-
Ok(Keyring::new(key.id))
299+
Ok(Keyring::new_impl(key.id))
291300
}
292301

293302
fn request_impl(&self, type_: &str, description: &str) -> Result<KeyringSerial> {
@@ -306,7 +315,7 @@ impl Keyring {
306315
where D: AsRef<str>,
307316
{
308317
let res = self.request_impl("user", description.as_ref())?;
309-
check_call(res as libc::c_long, Key::new(res))
318+
check_call(res as libc::c_long, Key::new_impl(res))
310319
}
311320

312321
/// Requests a keyring with the given description by searching the thread, process, and session
@@ -317,7 +326,7 @@ impl Keyring {
317326
where D: AsRef<str>,
318327
{
319328
let res = self.request_impl("keyring", description.as_ref())?;
320-
check_call(res as libc::c_long, Keyring::new(res))
329+
check_call(res as libc::c_long, Keyring::new_impl(res))
321330
}
322331

323332
fn request_fallback_impl(&self, type_: &str, description: &str, info: &str) -> Result<KeyringSerial> {
@@ -343,7 +352,7 @@ impl Keyring {
343352
I: AsRef<str>,
344353
{
345354
let res = self.request_fallback_impl("user", description.as_ref(), info.as_ref())?;
346-
check_call(res as libc::c_long, Key::new(res))
355+
check_call(res as libc::c_long, Key::new_impl(res))
347356
}
348357

349358
/// Requests a keyring with the given description by searching the thread, process, and session
@@ -357,7 +366,7 @@ impl Keyring {
357366
I: AsRef<str>,
358367
{
359368
let res = self.request_fallback_impl("keyring", description.as_ref(), info.as_ref())?;
360-
check_call(res as libc::c_long, Keyring::new(res))
369+
check_call(res as libc::c_long, Keyring::new_impl(res))
361370
}
362371

363372
/// Revokes the keyring.
@@ -449,7 +458,14 @@ pub struct Key {
449458
}
450459

451460
impl Key {
452-
fn new(id: KeyringSerial) -> Self {
461+
/// Instantiate a key from an ID.
462+
///
463+
/// This is unsafe because no key is known to exist with the given ID.
464+
pub unsafe fn new(id: KeyringSerial) -> Self {
465+
Self::new_impl(id)
466+
}
467+
468+
fn new_impl(id: KeyringSerial) -> Self {
453469
Key {
454470
id: id,
455471
}
@@ -459,15 +475,15 @@ impl Key {
459475
/// keyrings.
460476
pub fn request_key_auth_key(create: bool) -> Result<Self> {
461477
let res = unsafe { keyctl_get_keyring_ID(KEY_SPEC_REQKEY_AUTH_KEY, create as libc::c_int) };
462-
check_call(res as libc::c_long, Key::new(res))
478+
check_call(res as libc::c_long, Key::new_impl(res))
463479
}
464480

465481
/// Requests a key with the given description by searching the thread, process, and session
466482
/// keyrings.
467483
pub fn request<D>(description: D) -> Result<Self>
468484
where D: AsRef<str>,
469485
{
470-
Keyring::new(0).request_key(description)
486+
Keyring::new_impl(0).request_key(description)
471487
}
472488

473489
/// Requests a key with the given description by searching the thread, process, and session
@@ -479,7 +495,7 @@ impl Key {
479495
where D: AsRef<str>,
480496
I: AsRef<str>,
481497
{
482-
Keyring::new(0).request_key_with_fallback(description, info)
498+
Keyring::new_impl(0).request_key_with_fallback(description, info)
483499
}
484500

485501
/// Update the payload in the key.
@@ -495,31 +511,31 @@ impl Key {
495511

496512
/// Revokes the key. Requires `write` permission on the key.
497513
pub fn revoke(self) -> Result<()> {
498-
Keyring::new(self.id).revoke()
514+
Keyring::new_impl(self.id).revoke()
499515
}
500516

501517
/// Change the user which owns the key.
502518
///
503519
/// Requires the `setattr` permission on the key and the SysAdmin capability to change it to
504520
/// anything other than the current user.
505521
pub fn chown(&mut self, uid: libc::uid_t) -> Result<()> {
506-
Keyring::new(self.id).chown(uid)
522+
Keyring::new_impl(self.id).chown(uid)
507523
}
508524

509525
/// Change the group which owns the key.
510526
///
511527
/// Requires the `setattr` permission on the key and the SysAdmin capability to change it to
512528
/// anything other than a group of which the current user is a member.
513529
pub fn chgrp(&mut self, gid: libc::gid_t) -> Result<()> {
514-
Keyring::new(self.id).chgrp(gid)
530+
Keyring::new_impl(self.id).chgrp(gid)
515531
}
516532

517533
/// Set the permissions on the key.
518534
///
519535
/// Requires the `setattr` permission on the key and the SysAdmin capability if the current
520536
/// user does not own the key.
521537
pub fn set_permissions(&mut self, perms: KeyPermissions) -> Result<()> {
522-
Keyring::new(self.id).set_permissions(perms)
538+
Keyring::new_impl(self.id).set_permissions(perms)
523539
}
524540

525541
/// Retrieve metadata about the key.
@@ -528,7 +544,7 @@ impl Key {
528544
///
529545
/// If the kernel returns malformed data, the parser will panic.
530546
pub fn description(&self) -> Result<Description> {
531-
Keyring::new(self.id).description()
547+
Keyring::new_impl(self.id).description()
532548
}
533549

534550
/// Read the payload of the key. Requires `read` permissions on the key.
@@ -548,27 +564,27 @@ impl Key {
548564
///
549565
/// A timeout of `0` means "no expiration". Requires the `setattr` permission on the key.
550566
pub fn set_timeout(&mut self, timeout: u32) -> Result<()> {
551-
Keyring::new(self.id).set_timeout(timeout)
567+
Keyring::new_impl(self.id).set_timeout(timeout)
552568
}
553569

554570
/// The security context of the key.
555571
///
556572
/// Depends on the security manager loaded into the kernel (e.g., SELinux or AppArmor).
557573
pub fn security(&self) -> Result<String> {
558-
Keyring::new(self.id).security()
574+
Keyring::new_impl(self.id).security()
559575
}
560576

561577
/// Invalidates the key and schedules it for removal.
562578
///
563579
/// Requires the `search` permission on the key.
564580
pub fn invalidate(self) -> Result<()> {
565-
Keyring::new(self.id).invalidate()
581+
Keyring::new_impl(self.id).invalidate()
566582
}
567583

568584
/// Create an object to manage a key request.
569585
pub fn manage(&mut self) -> Result<KeyManager> {
570586
check_call(unsafe { keyctl_assume_authority(self.id) },
571-
KeyManager::new(Key::new(self.id)))
587+
KeyManager::new(Key::new_impl(self.id)))
572588
}
573589

574590
/// Compute a Diffie-Hellman prime for use as a shared secret or public key.

0 commit comments

Comments
 (0)