These functions (e.g., gr_free()), explicitly dereference the pointer and read the pointee. The /@out@/ comment, which is (almost) analogous to the [[gnu::access(write_only, ...)]] attribute, means that the pointee can be uninitialized, since it won't read it. There's a difference between /@out@/ and the GCC attribute: the attribute doesn't require that the call writes to the pointee, while /@out@/ requires that the pointee be fully initialized after the call, so it _must_ write to it. A guess of why it was used is that these functions are similar to free(3), which does not read the memory it frees, and so one would assume that if it doesn't read, write_only (or equivalents) are good. That's wrong in several ways: - free(3) does not read _nor_ write to the memory, so it would be slightly inappropriate to use write_only with it. It wouldn't be "wrong", but [[gnu::access(none, ...)]] would be more appropriate. - Because /@out@/ requires that the call writes to the pointee, it would be wrong to use it in free(3), which doesn't write to the pointee. - Our functions are similar to free(3) conceptually, but they don't behave like free(3), since they do read the memory (pointee) (and also write to it), and thus they're actually read_write. Link: <https://splint.org/manual/manual.html#undefined> Cc: Serge Hallyn <serge@hallyn.com> Signed-off-by: Alejandro Colomar <alx@kernel.org>
249 lines
4.7 KiB
C
249 lines
4.7 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
|
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
|
* SPDX-FileCopyrightText: 2001 , Michał Moskal
|
|
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
|
* SPDX-FileCopyrightText: 2007 - 2009, Nicolas François
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#ident "$Id$"
|
|
|
|
#include "prototypes.h"
|
|
#include "defines.h"
|
|
#include <shadow.h>
|
|
#include <stdio.h>
|
|
#include "commonio.h"
|
|
#include "getdef.h"
|
|
#include "shadowio.h"
|
|
#ifdef WITH_TCB
|
|
#include <tcb.h>
|
|
#include "tcbfuncs.h"
|
|
#endif /* WITH_TCB */
|
|
|
|
static /*@null@*/ /*@only@*/void *shadow_dup (const void *ent)
|
|
{
|
|
const struct spwd *sp = ent;
|
|
|
|
return __spw_dup (sp);
|
|
}
|
|
|
|
static void
|
|
shadow_free(/*@only@*/void *ent)
|
|
{
|
|
struct spwd *sp = ent;
|
|
|
|
spw_free (sp);
|
|
}
|
|
|
|
static const char *shadow_getname (const void *ent)
|
|
{
|
|
const struct spwd *sp = ent;
|
|
|
|
return sp->sp_namp;
|
|
}
|
|
|
|
static void *shadow_parse (const char *line)
|
|
{
|
|
return sgetspent (line);
|
|
}
|
|
|
|
static int shadow_put (const void *ent, FILE * file)
|
|
{
|
|
const struct spwd *sp = ent;
|
|
|
|
if ( (NULL == sp)
|
|
|| (valid_field (sp->sp_namp, ":\n") == -1)
|
|
|| (valid_field (sp->sp_pwdp, ":\n") == -1)
|
|
|| (strlen (sp->sp_namp) + strlen (sp->sp_pwdp) +
|
|
1000 > PASSWD_ENTRY_MAX_LENGTH)) {
|
|
return -1;
|
|
}
|
|
|
|
return (putspent (sp, file) == -1) ? -1 : 0;
|
|
}
|
|
|
|
static struct commonio_ops shadow_ops = {
|
|
shadow_dup,
|
|
shadow_free,
|
|
shadow_getname,
|
|
shadow_parse,
|
|
shadow_put,
|
|
fgets,
|
|
fputs,
|
|
NULL, /* open_hook */
|
|
NULL /* close_hook */
|
|
};
|
|
|
|
static struct commonio_db shadow_db = {
|
|
SHADOW_FILE, /* filename */
|
|
&shadow_ops, /* ops */
|
|
NULL, /* fp */
|
|
#ifdef WITH_SELINUX
|
|
NULL, /* scontext */
|
|
#endif /* WITH_SELINUX */
|
|
0400, /* st_mode */
|
|
0, /* st_uid */
|
|
0, /* st_gid */
|
|
NULL, /* head */
|
|
NULL, /* tail */
|
|
NULL, /* cursor */
|
|
false, /* changed */
|
|
false, /* isopen */
|
|
false, /* locked */
|
|
false, /* readonly */
|
|
false /* setname */
|
|
};
|
|
|
|
int spw_setdbname (const char *filename)
|
|
{
|
|
return commonio_setname (&shadow_db, filename);
|
|
}
|
|
|
|
/*@observer@*/const char *spw_dbname (void)
|
|
{
|
|
return shadow_db.filename;
|
|
}
|
|
|
|
bool spw_file_present (void)
|
|
{
|
|
if (getdef_bool ("FORCE_SHADOW"))
|
|
return true;
|
|
return commonio_present (&shadow_db);
|
|
}
|
|
|
|
int spw_lock (void)
|
|
{
|
|
#ifdef WITH_TCB
|
|
int retval = 0;
|
|
|
|
if (!getdef_bool ("USE_TCB")) {
|
|
#endif /* WITH_TCB */
|
|
return commonio_lock (&shadow_db);
|
|
#ifdef WITH_TCB
|
|
}
|
|
if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) {
|
|
return 0;
|
|
}
|
|
if (lckpwdf_tcb (shadow_db.filename) == 0) {
|
|
shadow_db.locked = 1;
|
|
retval = 1;
|
|
}
|
|
if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) {
|
|
return 0;
|
|
}
|
|
return retval;
|
|
#endif /* WITH_TCB */
|
|
}
|
|
|
|
int spw_open (int mode)
|
|
{
|
|
int retval = 0;
|
|
#ifdef WITH_TCB
|
|
bool use_tcb = getdef_bool ("USE_TCB");
|
|
|
|
if (use_tcb && (shadowtcb_drop_priv () == SHADOWTCB_FAILURE)) {
|
|
return 0;
|
|
}
|
|
#endif /* WITH_TCB */
|
|
retval = commonio_open (&shadow_db, mode);
|
|
#ifdef WITH_TCB
|
|
if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) {
|
|
return 0;
|
|
}
|
|
#endif /* WITH_TCB */
|
|
return retval;
|
|
}
|
|
|
|
/*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name)
|
|
{
|
|
return commonio_locate (&shadow_db, name);
|
|
}
|
|
|
|
int spw_update (const struct spwd *sp)
|
|
{
|
|
return commonio_update (&shadow_db, sp);
|
|
}
|
|
|
|
int spw_remove (const char *name)
|
|
{
|
|
return commonio_remove (&shadow_db, name);
|
|
}
|
|
|
|
int spw_rewind (void)
|
|
{
|
|
return commonio_rewind (&shadow_db);
|
|
}
|
|
|
|
/*@observer@*/ /*@null@*/const struct spwd *spw_next (void)
|
|
{
|
|
return commonio_next (&shadow_db);
|
|
}
|
|
|
|
int spw_close (void)
|
|
{
|
|
int retval = 0;
|
|
#ifdef WITH_TCB
|
|
bool use_tcb = getdef_bool ("USE_TCB");
|
|
|
|
if (use_tcb && (shadowtcb_drop_priv () == SHADOWTCB_FAILURE)) {
|
|
return 0;
|
|
}
|
|
#endif /* WITH_TCB */
|
|
retval = commonio_close (&shadow_db);
|
|
#ifdef WITH_TCB
|
|
if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) {
|
|
return 0;
|
|
}
|
|
#endif /* WITH_TCB */
|
|
return retval;
|
|
}
|
|
|
|
int spw_unlock (void)
|
|
{
|
|
#ifdef WITH_TCB
|
|
int retval = 0;
|
|
|
|
if (!getdef_bool ("USE_TCB")) {
|
|
#endif /* WITH_TCB */
|
|
return commonio_unlock (&shadow_db);
|
|
#ifdef WITH_TCB
|
|
}
|
|
if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) {
|
|
return 0;
|
|
}
|
|
if (ulckpwdf_tcb () == 0) {
|
|
shadow_db.locked = 0;
|
|
retval = 1;
|
|
}
|
|
if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) {
|
|
return 0;
|
|
}
|
|
return retval;
|
|
#endif /* WITH_TCB */
|
|
}
|
|
|
|
struct commonio_entry *__spw_get_head (void)
|
|
{
|
|
return shadow_db.head;
|
|
}
|
|
|
|
void __spw_del_entry (const struct commonio_entry *ent)
|
|
{
|
|
commonio_del_entry (&shadow_db, ent);
|
|
}
|
|
|
|
/* Sort with respect to passwd ordering. */
|
|
int spw_sort ()
|
|
{
|
|
#ifdef WITH_TCB
|
|
if (getdef_bool ("USE_TCB")) {
|
|
return 0;
|
|
}
|
|
#endif /* WITH_TCB */
|
|
return commonio_sort_wrt (&shadow_db, __pw_get_db ());
|
|
}
|