From: finkler <finkler@officinamentis.org>
To: musl@lists.openwall.com
Subject: Re: utmpx support
Date: Fri, 16 Mar 2012 15:05:18 +0100 [thread overview]
Message-ID: <jjvhb4$tgv$1@dough.gmane.org> (raw)
In-Reply-To: <20120306013028.GY184@brightrain.aerifal.cx>
[-- Attachment #1: Type: text/plain, Size: 2094 bytes --]
On 06.03.2012 02:30, Rich Felker wrote:
> On Sun, Mar 04, 2012 at 08:10:36PM +0100, finkler wrote:
> Append mode is definitely not correct if you want to be able to
> overwrite existing entries.
Changed it to r+ and r
> I'm confused about the intent of this code.. Presumably it's supposed
> to modify the entry it just found (relying on getutxid leaving the
> file at the right position), but that's not going to work because the
> file is opened in append mode.
>
> Also, -(sizeof ut) is not a valid offset; it's almost SIZE_MAX. If you
> were using fseeko, this would result in a gigantic offset (rather than
> a negative one) after the conversion; with fseek (which takes a long),
> it should convert back to the desired negative value, but for safety
> you should cast to a signed type *before* negating the result of
> sizeof
Made the cast inside the function call.
> There's also the issue that there's absolutely no locking on updates,
> so if multiple apps try to add/update utmp entries at the same time,
> the file would be corrupted. This could be fixed by using an fcntl
> lock on fileno(f) for the duration of the function.
I added a lock, however, I am unsure whether I should use a lock that
waits until it is free or not, and whether I should lock the whole file,
or just the portion which is about to be written.
Right now I use a waiting lock, and lock the whole file.
> Here strcmp is being called on data that was read from a file with no
> validation. This is potentially a security issue (DoS); if the file
> does not contain a null-terminated string, strcmp could run past the
> end of the buffer and eventually segfault and crash the calling
> program. It's probably hard to trigger the issue since the string for
> comparison is also located in a utmp structure, but I think there
> should be some validation, probably just fixing invalid data right
> after the fread call so it never leaks out.
I changed it to use strncmp with the sizeof the respective struct field,
is this enough?
Thank you very much for your time, I attached the reworked version.
[-- Attachment #2: utmpx.c --]
[-- Type: text/plain, Size: 2052 bytes --]
#include <utmpx.h>
#include <stddef.h>
#include "libc.h"
#define _PATH_UTMPX "/etc/utmp"
static FILE *f;
static struct utmpx ut;
void endutxent(void)
{
if (f == NULL) return;
fclose(f);
f == NULL;
}
void setutxent(void)
{
if (f == NULL) return;
rewind(f);
}
struct utmpx *getutxent(void)
{
if (f == NULL) {
f = fopen(_PATH_UTMPX, "r+");
if (f == NULL) {
f = fopen(_PATH_UTMPX, "r");
if (f == NULL) return NULL;
}
}
if (fread(&ut, sizeof ut, 1, f)) return &ut;
return NULL;
}
struct utmpx *getutxid(const struct utmpx *id)
{
while(getutxent()) {
switch (id->ut_type) {
case BOOT_TIME:
case OLD_TIME:
case NEW_TIME:
if (id->ut_type == ut.ut_type) return &ut;
break;
case INIT_PROCESS:
case LOGIN_PROCESS:
case USER_PROCESS:
case DEAD_PROCESS:
if (id->type == ut.ut_type && !strncmp(id->ut_id, ut.ut_id, sizeof ut.ut_id)) return &ut;
break;
}
}
return NULL;
}
struct utmpx *getutxline(const struct utmpx *line)
{
while(getutxent()) {
switch (ut.ut_type) {
case LOGIN_PROCESS:
case USER_PROCESS:
if (!strncmp(line->ut_line, ut.ut_line, sizeof ut.ut_line)) return &ut;
break;
}
}
return NULL;
}
struct utmpx *pututxline(const struct utmpx *utmpx)
{
struct flock fl;
size_t n;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
if (fcntl(fileno(f), F_SETLKW, &fl) < 0) return NULL;
setutxent();
if (getutxid(utmpx)) fseek(f, -((long)(sizeof ut)), SEEK_CUR);
n = fwrite(&ut, sizeof ut, 1, f);
fl.l_type = F_UNLCK;
fcntl(fileno(f), F_SETLK, &fl);
if (n == 1)
return &ut;
return NULL;
}
void updwtmpx(const char *f, const struct utmpx *u)
{
}
weak_alias(endutxent, endutent);
weak_alias(setutxent, setutent);
weak_alias(getutxent, getutent);
weak_alias(getutxid, getutid);
weak_alias(getutxline, getutline);
weak_alias(pututxline, pututline);
weak_alias(updwtmpx, updwtmp);
next prev parent reply other threads:[~2012-03-16 14:05 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-04 17:41 finkler
2012-03-04 18:18 ` Rich Felker
2012-03-04 19:10 ` finkler
2012-03-06 1:30 ` Rich Felker
2012-03-16 14:05 ` finkler [this message]
2012-03-06 1:39 ` Rich Felker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='jjvhb4$tgv$1@dough.gmane.org' \
--to=finkler@officinamentis.org \
--cc=musl@lists.openwall.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).