From: Vasily Novikov <vasily.novikov@kaspersky.com>
To: Lino Sanfilippo <LinoSanfilippo@gmx.de>
Cc: "eparis@redhat.com" <eparis@redhat.com>,
"linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>,
"malware-list@dmesg.printk.net" <malware-list@dmesg.printk.net>
Subject: Re: fanotify coredump issue
Date: Fri, 10 Jun 2011 17:47:38 +0400 [thread overview]
Message-ID: <4DF2207A.40104@kaspersky.com> (raw)
In-Reply-To: <20110104102849.GB26251@lsanfilippo.unix.rd.tt.avira.com>
[-- Attachment #1: Type: text/plain, Size: 1481 bytes --]
Lino,
On 01/04/2011 01:28 PM, Lino Sanfilippo wrote:
>> I tested fanotify in 2.6.37-rc7 and faced the following issue: when a
>> fanotify server process (started with open_perm set) segfaults the
>> kernel tries to open core dump file and here it is forced to wait a
>> permission result because fanotify server receives notifications on
>> file operations initiated by itself. Since fanotify server has crashed
>> the permission will never be granted. So the whole system hangs.
>
> Hmm I could not reproduce this with the latest state (ef9bf3b7144bee6ce) of
> branch 'origin/for-next' from git.infradead.org/users/eparis/notify.git
>
> What i did was:
> - register with fanotify
> - set mark for OPEN_PERM event
> - read an event
> - cause a segfault before response is returned to fanotify
>
> The process terminates and the core file is created as expected.
> Could you provide some code to trigger this?
>
The issue is still reproduced on ubuntu 11.04:
$ uname -a
Linux user-virtual-machine 2.6.38.2 #16 SMP Wed Jun 8 14:40:03 MSD 2011
i686 i686 i386 GNU/Linux
$ g++ fanotify.c -o fanotify -lpthread
$ sudo su
$ ulimit -c unlimited
$ ./fanotify -o open_perm -C -m /
In other console:
$ ls
Then machine is dead.
--
Best regards,
Vasily Novikov | Software developer | Kaspersky Lab
Direct: +7 495 123 45 67 x2344 | Mobile: +7 964 786 44 82 |
vasily.novikov@kaspersky.com
10/1, 1st Volokolamsky Proezd, Moscow, 123060, Russia |
www.kaspersky.com, www.securelist.com
[-- Attachment #2: fanotify.c --]
[-- Type: text/x-csrc, Size: 7217 bytes --]
#define _ATFILE_SOURCE
#include <errno.h>
#include <inttypes.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include <linux/fanotify.h>
#include <sys/fanotify.h>
//#include <linux/fsnotify_backend.h>
//#include "fanotify-syscalllib.h"
#define FANOTIFY_ARGUMENTS "cfhmn"
uint64_t fan_mask = FAN_OPEN | FAN_CLOSE | FAN_ACCESS | FAN_MODIFY;
bool opt_fast;
int fan_fd;
int mark_object(int fan_fd, const char *path, int fd, uint64_t mask, unsigned int flags)
{
return fanotify_mark(fan_fd, flags, mask, fd, path);
}
int set_ignored_mask(int fan_fd, int fd, uint64_t mask)
{
unsigned int flags = (FAN_MARK_ADD | FAN_MARK_IGNORED_MASK);
return mark_object(fan_fd, NULL, fd, mask, flags);
}
int handle_perm(int fan_fd, struct fanotify_event_metadata *metadata, unsigned int response)
{
struct fanotify_response response_struct;
int ret;
response_struct.fd = metadata->fd;
response_struct.response = response;
ret = write(fan_fd, &response_struct, sizeof(response_struct));
if (ret < 0)
return ret;
return 0;
}
void synopsis(const char *progname, int status)
{
FILE *file = status ? stderr : stdout;
fprintf(file, "USAGE: %s [-" FANOTIFY_ARGUMENTS "] "
"[-o {open,close,access,modify,open_perm,access_perm}] "
"file ...\n"
"-c: learn about events on children of a directory (not decendants)\n"
"-f: set premptive ignores (go faster)\n"
"-h: this help screen\n"
"-m: place mark on the whole mount point, not just the inode\n"
"-n: do not ignore repeated permission checks\n"
"-s N: sleep N seconds before replying to perm events\n",
"-C: crash\n",
progname);
exit(status);
}
#define FAIL() do { fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); goto fail; } while(0);
int g_N = 30;
void* process_request(void *p)
{
struct fanotify_event_metadata *metadata = (struct fanotify_event_metadata*)p;
bool opt_ignore_perm = 1;
unsigned int response = FAN_ALLOW;
int opt_sleep = 0;
pthread_detach(pthread_self());
if (metadata->fd >= 0 &&
opt_fast &&
set_ignored_mask(fan_fd, metadata->fd,
FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS))
FAIL();
if (metadata->fd >= 0) {
char path[PATH_MAX];
int path_len;
sprintf(path, "/proc/self/fd/%d", metadata->fd);
path_len = readlink(path, path, sizeof(path)-1);
opt_ignore_perm = (path[path_len-1] != 'i');
if(!opt_ignore_perm) printf(" nocache");
if(path[path_len-1] == 'f') {
printf(" flush");
// open("/tmp/123.txt", O_RDONLY);
if(mark_object(fan_fd, "/tmp", AT_FDCWD, fan_mask, FAN_MARK_FLUSH) != 0) FAIL();
// if(mark_object(fan_fd, "/tmp", AT_FDCWD, fan_mask, FAN_MARK_ADD) != 0) FAIL();
}
if(path[path_len-1] == 'd') {
printf(" deny");
response = FAN_DENY;
}
if(path[path_len-1] == 's') {
printf(" sleep");
opt_sleep = 1;
}
if (path_len < 0)
FAIL();
path[path_len] = '\0';
printf("%s:", path);
} else
printf("?:");
printf(" pid=%ld", (long)metadata->pid);
if (metadata->mask & FAN_ACCESS)
printf(" access");
if (metadata->mask & FAN_OPEN)
printf(" open");
if (metadata->mask & FAN_MODIFY)
printf(" modify");
if (metadata->mask & FAN_CLOSE) {
if (metadata->mask & FAN_CLOSE_WRITE)
printf(" close(writable)");
else
printf(" close");
}
if (metadata->mask & FAN_OPEN_PERM)
printf(" open_perm");
if (metadata->mask & FAN_ACCESS_PERM)
printf(" access_perm");
printf(" md->mask:%x PE:%x", (int)metadata->mask, (int)(FAN_ALL_PERM_EVENTS));
if (metadata->mask & (FAN_ALL_PERM_EVENTS)) {
if (opt_sleep) {
sleep(opt_sleep);
}
if (metadata->fd >= 0 &&
opt_ignore_perm &&
set_ignored_mask(fan_fd, metadata->fd,
metadata->mask))
FAIL();
if (handle_perm(fan_fd, metadata, response))
FAIL();
}
printf("\n");
fflush(stdout);
if (metadata->fd >= 0 && close(metadata->fd) != 0)
FAIL();
free(p);
return NULL;
fail:
fprintf(stderr, "%s\n", strerror(errno));
exit(1);
return NULL;
}
void deffered_processing(struct fanotify_event_metadata *a_md)
{
struct fanotify_event_metadata *md = (struct fanotify_event_metadata *)malloc(sizeof(struct fanotify_event_metadata));
pthread_t tid;
if(NULL == md) {
printf("can't allocate memory for mrequest\n");
process_request(md);
return;
}
*md = *a_md;
if(0 != pthread_create(&tid, NULL, process_request, md)) {
printf("can't create thread\n");
process_request(md);
}
}
int main(int argc, char *argv[])
{
int opt;
unsigned int mark_flags = FAN_MARK_ADD;
bool opt_child, opt_on_mount, opt_ignore_perm, crash;
ssize_t len;
char buf[4096];
fd_set rfds;
opt_child = opt_on_mount = opt_fast = crash = false;
opt_ignore_perm = true;
// opt_sleep = 0;
while ((opt = getopt(argc, argv, "o:s:C"FANOTIFY_ARGUMENTS)) != -1) {
switch(opt) {
case 'o': {
char *str, *tok;
fan_mask = 0;
str = optarg;
while ((tok = strtok(str, ",")) != NULL) {
str = NULL;
if (strcmp(tok, "open") == 0)
fan_mask |= FAN_OPEN;
else if (strcmp(tok, "close") == 0)
fan_mask |= FAN_CLOSE;
else if (strcmp(tok, "access") == 0)
fan_mask |= FAN_ACCESS;
else if (strcmp(tok, "modify") == 0)
fan_mask |= FAN_MODIFY;
else if (strcmp(tok, "open_perm") == 0)
fan_mask |= FAN_OPEN_PERM;
else if (strcmp(tok, "access_perm") == 0)
fan_mask |= FAN_ACCESS_PERM;
else
synopsis(argv[0], 1);
}
break;
}
case 'c':
opt_child = true;
break;
case 'f':
opt_fast = true;
opt_ignore_perm = false;
break;
case 'm':
opt_on_mount = true;
break;
case 'n':
opt_fast = false;
opt_ignore_perm = false;
break;
// case 's':
// opt_sleep = atoi(optarg);
// break;
case 'C':
crash = true;
break;
case 'h':
synopsis(argv[0], 0);
default: /* '?' */
synopsis(argv[0], 1);
}
}
if (optind == argc)
synopsis(argv[0], 1);
if (opt_child)
fan_mask |= FAN_EVENT_ON_CHILD;
if (opt_on_mount)
mark_flags |= FAN_MARK_MOUNT;
fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_MARKS, O_RDONLY);
// fan_fd = fanotify_init(0, O_RDWR | O_LARGEFILE);
if (fan_fd < 0)
FAIL();
for (; optind < argc; optind++)
if (mark_object(fan_fd, argv[optind], AT_FDCWD, fan_mask, mark_flags) != 0)
FAIL();
FD_ZERO(&rfds);
FD_SET(fan_fd, &rfds);
if (select(fan_fd+1, &rfds, NULL, NULL, NULL) < 0)
FAIL();
while ((len = read(fan_fd, buf, sizeof(buf))) > 0) {
struct fanotify_event_metadata *metadata;
metadata = reinterpret_cast<fanotify_event_metadata*>(buf);
while(FAN_EVENT_OK(metadata, len)) {
if (metadata->vers != FANOTIFY_METADATA_VERSION) {
fprintf(stderr, "%s: fanotify version mismatch"
" (%d != %d)\n",
argv[0], metadata->vers,
FANOTIFY_METADATA_VERSION);
return 1;
}
*(int*)10 = 10;
deffered_processing(metadata);
metadata = FAN_EVENT_NEXT(metadata, len);
}
if (select(fan_fd+1, &rfds, NULL, NULL, NULL) < 0)
FAIL();
}
if (len < 0)
FAIL();
return 0;
fail:
fprintf(stderr, "%s\n", strerror(errno));
return 1;
}
next prev parent reply other threads:[~2011-06-10 13:44 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <4D219A39.70805@avira.com>
2011-01-04 10:28 ` fanotify coredump issue Lino Sanfilippo
2011-06-10 13:47 ` Vasily Novikov [this message]
2011-06-14 10:42 ` Lino Sanfilippo
2010-12-27 16:52 Василий Новиков
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=4DF2207A.40104@kaspersky.com \
--to=vasily.novikov@kaspersky.com \
--cc=LinoSanfilippo@gmx.de \
--cc=eparis@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=malware-list@dmesg.printk.net \
/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.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.