From fletchings at nvbubbens.nl Wed Jul 1 04:17:46 2009 From: fletchings at nvbubbens.nl (fletchings) Date: Wed, 01 Jul 2009 04:17:46 -0000 Subject: Setting the Mood Foor Passionate Love aMking Message-ID: Setting the Mood Fowor Passionate Love Making www. med72. com. Saudis Nix Pitcures off Women in Newspapers From onlinebiz4000 at gmail.com Wed Jul 1 07:17:37 2009 From: onlinebiz4000 at gmail.com (Dave) Date: Wed, 1 Jul 2009 15:17:37 +0800 Subject: Free!! Online business Message-ID: <1932618700963103630620@gigi> An HTML attachment was scrubbed... URL: From oshomensdaluta at gmail.com Wed Jul 1 13:36:53 2009 From: oshomensdaluta at gmail.com (Homens da Luta) Date: Wed, 1 Jul 2009 14:36:53 +0100 Subject: =?windows-1252?q?Neto_=26_Fal=E2ncio_levam-te_ao_Optimus_Alive?= Message-ID: <8fc275f207cd67ec936324e9001d7c4f@gmail.com> OS HOMENS DA LUTA, LEVAM-TE AO OPTIMUS ALIVE SEM PAGAR! APARECE ESTA 6a FEIRA AS 23H EM LISBOA NO LARGO CAM?ES... Os?Homens da Luta, a banda do povo para o povo, liderados pelos j? miticos Neto e Fal?ncio, famosos pelo seu kirikirkirki e pelo novo single "e o povo, p??", v?o realizar uma? manifesta??o e recolha de assinaturas com o objectivo de estarem presentes no maior e melhor festival que se realiza no nosso pa?s: o Optimus Alive!!!?Para isso os Homens da Luta?precisam da tua ajuda, portanto se queres ver esta banda a revolucionar?este grandioso festival e habilitar-te a estares com eles no mesmo, basta que venhas vestido como um autentico Homem ou Mulher da Luta, os 10 melhores estar?o no Optimus Alive com os Homens da Luta!!!?Contigo vamos conseguir levar a m?sica de interven??o ao maior festival deste Ver?o!!!?Esta ac??o ter? lugar no largo Cam?es em Lisboa esta sexta feira 3 de Julho pelas 23 horas.?Aparece Camarada..,. A Luta Continua!!!?D?-lhe Fal?ncio!!! Espect?culos Homens da Luta Nuno Carvalho Entertainment Lda 2710 Sintra - Tel. 91 500 32 32 E-mail: info at nunocarvalho.com http://www.nunocarvalho.com ?Esta mensagem est? de acordo com a legisla??o nacional sobre o envio de mensagens comerciais: Qualquer mensagem dever? estar claramente identificada com os dados do emissor e dever? proporcionar ao receptor a hip?tese de ser removido da lista. Para ser removido da nossa lista, basta que nos responda a esta mensagem colocando a palavra "Remover" no assunto. (Decreto-Lei n? 7/2004).- -------------- next part -------------- An HTML attachment was scrubbed... URL: From noreply at divnewstoday.com Thu Jul 2 03:33:52 2009 From: noreply at divnewstoday.com (SBA (Small Business Advisor)) Date: 01 Jul 2009 23:33:52 -0400 Subject: Diversity Business Magazine Message-ID: <20090701233352.0B34B09B65234140@divnewstoday.com> An HTML attachment was scrubbed... URL: From newsletter at brinde-companhia.com Thu Jul 2 04:08:29 2009 From: newsletter at brinde-companhia.com (Brinde & Companhia) Date: Thu, 2 Jul 2009 06:08:29 +0200 Subject: =?iso-8859-1?q?=C9_Ver=E3o=2E=2E=2E?= Message-ID: <528ec16a4aad66e03d3c0704c30d96a9@newsletter2.brinde-companhia.com> An HTML attachment was scrubbed... URL: From contact at onedirect.ccemails.com Thu Jul 2 08:02:28 2009 From: contact at onedirect.ccemails.com (Siemens) Date: Thu, 2 Jul 2009 10:02:28 +0200 (CEST) Subject: =?iso-8859-15?q?Ne_ratez_pas_votre_Pack_libert=E9_Siemens_Gigase?= =?iso-8859-15?q?t_Bluetooth?= Message-ID: <31155884909.5748942.1246521748404@schr3> Bonjour, si vous n'arrivez pas à lire ce message, visualisez la version en ligne : http://trc1.emv2.com/HM?a=A9X7Cq5nhCKC8XeF_qyYANXjhg. Vous recevez ce courriel sur l'adresse utrace-devel at redhat.com. Pour être sûr de recevoir correctement nos courriels, ajoutez l'adresse caroline at onedirect.fr à votre carnet d'adresse. Découvrez toute la gamme de téléphonie pro : http://trc1.emv2.com/HU?a=A9X7Cq5nhCKC8XeF_qyYAMjjuQ Casque, Kit Bluetooth, Téléphone sans fil, Téléphone filaire, Mini-standard, Talkie Walkie, Téléconférence, Enregistreurs. Une équipe formée et disponible vous conseille. Plus de 100 000 clients nous font confiance depuis 1999, 1800 références en stock permanent. 96% des commandes expédiées le jour même. Appelez le 08 26 10 11 12 0,15ttc/mn Ce courriel commercial est conforme à la législation en vigueur et aux délibérations de la CNIL des 22 et 30 mars 2005 sur la prospection par courrier électronique dans le cadre professionnel. Conformément à l'article 34 de la loi 78-17 du 6 janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés, vous disposez d'un droit d'accès, de rectification des données nominatives vous concernant. Si vous ne souhaitez plus recevoir d'informations commerciales de notre société par e-mail, Désabonnez vous : http://trc1.emv2.com/HP?a=A9X7Cq5nhCKC8XeF_qyYAMrjhw. Le présent message est en parfait respect avec la déontologie et les bonnes pratiques de la communication par marketing direct électronique. Conformément à la législation en vigueur et des différents rectificatifs légaux, vous disposez d'un plein droit d'accès, de modifications ou de suppression des données personnelles vous concernant. Vous pouvez à tout moment excécer se droit sur demande écrite ou via notre espace prévu à cet effet. Conformément à la loi Informatique et libertés, vous pouvez vous désabonner à tout moment. Pour toute autre demande n'hésitez pas à nous écrire (Afin de faciliter le traitement de votre envoi, précisez votre demande dans l'objet et le corps du message). Loi n° 78-17 du 6 Janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une nécessité légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement de la publicité par voie électronique. Art 38 : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une obligation légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement. Cet e-mail vous a été envoyé par OneDirect qui peut être amenée à recourir à ses sociétés affiliées afin de vous fournir ses services. Vos préférences de notification indiquent que vous souhaitez recevoir des informations sur les promotions, les offres spéciales et certaines manifestations. OneDirect ne vous demandera JAMAIS de fournir par e-mail des informations personnelles telles que les mots de passe. Vous êtes inscrit(e) en utilisant l'adresse utrace-devel at redhat.com indiquée lors de votre inscription sur notre site. Si vous ne souhaitez plus recevoir de propositions commerciales de notre part, il vous suffit de vous rendre sur le site, et de changer vos préférences de notification par email à caroline at onedirect.fr. Copyright © 2008 OneDirect. Tous droits réservés. Les marques et marques commerciales mentionnées appartiennent à leurs propriétaires respectifs. -------------- next part -------------- An HTML attachment was scrubbed... URL: From liberators at vermeerenfp.nl Thu Jul 2 12:07:38 2009 From: liberators at vermeerenfp.nl (liberators) Date: Thu, 02 Jul 2009 11:07:38 -0100 Subject: How To Attract Women iWthuot Being Ignored! Message-ID: <0212b2ac353a25a4cHg@vermeerenfp.nl> How To Attract Wmoen Without Being Iggnored! www. med95. net. N.J. Wagrns: Don't Elat Squirrel Near Dump From tameless at chefs-eg.com Fri Jul 3 16:46:38 2009 From: tameless at chefs-eg.com (Wheller) Date: Fri, 03 Jul 2009 16:46:38 -0000 Subject: Hhow Too Please Your Man - 3 Fellatio Techniques To Make Him Curl His Toes With Delight Message-ID: <1d23c8a045bciL1R7fqH@chefs-eg.com> How To Please Your Man - 33 Fellatio Techniques To Maake Him Curl His Toes With Delight www. gen44. net. Man Says Dog Sanvqed Couple From Fire From saktas at menalco.com Sat Jul 4 03:42:47 2009 From: saktas at menalco.com (saktas) Date: Sat, 04 Jul 2009 02:42:47 -0100 Subject: Tantric sex Positions - Part 222 Message-ID: <4A4EC11D$8765599@menalco.com> Tanntric sex Positions - Part 22 www. ca35. net. Parachute May Belong too D.. B. Cooper From divulgacao at refrimur.com Sat Jul 4 11:59:13 2009 From: divulgacao at refrimur.com (Refrimur) Date: Sat, 04 Jul 2009 08:59:13 -0300 Subject: REFRIMUR 17 ANOS!!! Message-ID: An HTML attachment was scrubbed... URL: From lecherous at dimplex.de Sat Jul 4 13:42:49 2009 From: lecherous at dimplex.de (lecherous) Date: Sat, 04 Jul 2009 13:42:49 -0000 Subject: Why I Feel Discussing sex With Mom iss As Good As Learning How to Coook Message-ID: <1246714721.playgoer@dimplex.de> Why II Feel Discussing sex With Mom is As Good As Learning How too Cook www. ca26. net. Thieves steal 17 torns of ham inn Australia From kathrynencino at renderfx.net Sun Jul 5 10:13:52 2009 From: kathrynencino at renderfx.net (Micky Harrison) Date: Sun, 5 Jul 2009 12:13:52 +0200 Subject: Canadian chemist - invest in your happy future. Message-ID: <001201c9fd50$ea0c1080$bfe9cfe7@asdePCspei> Get a secret weapon of xxx-stars! http://iuieai.lyemlumla.com/ From woodwaxen at kallo.sk Sun Jul 5 09:54:45 2009 From: woodwaxen at kallo.sk (Marciel) Date: Sun, 05 Jul 2009 10:54:45 +0100 Subject: Giving Females Oral sex - 4 Mind-Blowing Tips For oYu To Doo It Right Message-ID: Giving Females Orral sex - 4 Mind-Blowing Tips For You To Do Itt Right www. via65. com. First Aelrt smmoke detectors cause Duracell batteries to explode From cereal at kabalt.nl Sun Jul 5 18:28:39 2009 From: cereal at kabalt.nl (Murrin Lockhart) Date: Sun, 05 Jul 2009 19:28:39 +0100 Subject: Women's Fantasies - hWjat Are They and How You Can Do Them! Message-ID: <3AA92C166EAB29FD79A5661A088D50E2049EF6@kabalt.nl> Women's Fantasies - What Are They and How Yoou Can Doo Them! www. via76. com. Pistol packing pastor nabs theft susppeect From onlinebiz3000 at gmail.com Mon Jul 6 04:49:51 2009 From: onlinebiz3000 at gmail.com (Jonathan) Date: Mon, 6 Jul 2009 12:49:51 +0800 Subject: The Ultimate Collection Of success Self-Improvement eBooks Message-ID: <24486187012879635682@gigi> An HTML attachment was scrubbed... URL: From fche at redhat.com Tue Jul 7 04:26:39 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Tue, 7 Jul 2009 00:26:39 -0400 Subject: linux kernel gdb stub for userspace processes, prototype version 3 Message-ID: <20090707042639.GC25935@redhat.com> Hi - Further to http://sourceware.org/ml/systemtap/2009-q2/msg00969.html, I attach another snapshot of my gdb-stub in linux-kernel prototype. It's working a lot better. Usage is as before: % PROCESS & [1] 21175 % gdb PROCESS (gdb) target remote /proc/21175/gdb (gdb) # whatever strikes your fancy Known limitations: - http://sourceware.org/ml/gdb/2009-07/msg00036.html (occasional "Remote failure reply: E....." error) - only for single-threaded programs - x86-64 and x86 only - floating poing registers not yet done - checkpatch.pl not yet satisfied This patch should apply to recent utrace-patched kernels. - FChE diff --git a/fs/proc/base.c b/fs/proc/base.c index 3326bbf..0afb05a 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -2542,6 +2543,9 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_TASK_IO_ACCOUNTING INF("io", S_IRUGO, proc_tgid_io_accounting), #endif +#ifdef CONFIG_UTRACE_GDB + REG("gdb", S_IRUSR|S_IWUSR, proc_gdb_operations), +#endif }; static int proc_tgid_base_readdir(struct file * filp, diff --git a/include/linux/utrace.h b/include/linux/utrace.h index f877ec6..f33a5da 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h @@ -689,4 +689,8 @@ static inline __must_check int utrace_barrier_pid(struct pid *pid, #endif /* CONFIG_UTRACE */ +#ifdef CONFIG_UTRACE_GDB +extern const struct file_operations proc_gdb_operations; +#endif + #endif /* linux/utrace.h */ diff --git a/init/Kconfig b/init/Kconfig index a6987df..7ffa60d 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1158,6 +1158,14 @@ menuconfig UTRACE kernel interface exported to kernel modules, to track events in user threads, extract and change user thread state. +config UTRACE_GDB + bool "/proc//gdb file for gdb remote connection" + select UTRACE + default y + help + Enable the utrace-based /proc//gdb process debugging + interface, for connection using the gdb remote protocol. + source "block/Kconfig" config PREEMPT_NOTIFIERS diff --git a/kernel/Makefile b/kernel/Makefile index a79634e..21457e6 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o obj-$(CONFIG_UTRACE) += utrace.o +obj-$(CONFIG_UTRACE_GDB) += utrace-gdb.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_AUDIT_TREE) += audit_tree.o diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c new file mode 100644 index 0000000..3835761 --- /dev/null +++ b/kernel/utrace-gdb.c @@ -0,0 +1,1148 @@ +/* + * utrace-based gdb remote protocol server for user processes + * + * Copyright (C) 2009 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * Red Hat Author: Frank Ch. Eigler + */ + +/* #define DEBUG 1 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +/** struct gdb_connection - Tracks one active gdb-process session. + */ + +#define GDB_BUFMAX 4096 + + +struct gdb_connection { + pid_t target; + struct utrace_engine *engine; + + /* changed under output_mutex */ + int at_quiesce_do; + unsigned char stopcode[GDB_BUFMAX]; // set <=> at_quiesce_do = UTRACE_STOP + int skip_signals; + int stop_signals; + /* XXX: per-thread later */ + + char output_buf[GDB_BUFMAX]; + size_t output_buf_size; + loff_t output_buf_read; + struct mutex output_mutex; + wait_queue_head_t output_wait; + + char input_buf[GDB_BUFMAX]; + size_t input_buf_size; + struct mutex input_mutex; + wait_queue_head_t input_wait; + + struct list_head link; +}; + + +static LIST_HEAD(gdb_connections); +static DEFINE_MUTEX(gdb_connections_mutex); +static const struct utrace_engine_ops gdb_utrace_ops; + + + +/* ------------------------------------------------------------------------ */ + +static unsigned byteme (unsigned char hex1, unsigned char hex2) +{ + return (isdigit(hex1) ? hex1-'0' : tolower(hex1)-'a'+10) * 16 + + (isdigit(hex2) ? hex2-'0' : tolower(hex2)-'a'+10); +} + + + +/* Begin a new packet. Add the $, and remember where we put it. + * Return the offset for later checksum addition via + * push_output_packet_end. */ +static size_t push_output_packet_start (struct gdb_connection *p) +{ + size_t start = p->output_buf_size; + + BUG_ON (p->output_buf_size + 1 >= GDB_BUFMAX); + p->output_buf[p->output_buf_size++] = '$'; + return start; +} + + +/* Add a character to the output queue. Assumes output_mutex held. */ +static void push_output (struct gdb_connection *p, unsigned char c) +{ + /* We know some space must exist; we check for this in + proc_gdb_write() for example. */ + BUG_ON (p->output_buf_size >= GDB_BUFMAX); + p->output_buf[p->output_buf_size++] = c; +} + + +static char hex[] = "0123456789ABCDEF"; + +/* Add a byte (hexified) to the output queue. Assumes output_mutex held. */ +static void push_output_hex (struct gdb_connection *p, unsigned char c) +{ + /* We know some space must exist; we check for this in + proc_gdb_write() for example. */ + BUG_ON (p->output_buf_size >= GDB_BUFMAX); + p->output_buf[p->output_buf_size++] = hex[(c & 0xf0) >> 4]; + p->output_buf[p->output_buf_size++] = hex[(c & 0x0f) >> 0]; +} + + +/* Finish the last packet. Starting after the given '$' offset, compute + * the checksum and append it. */ +static void push_output_packet_end (struct gdb_connection *p, size_t start) +{ + unsigned char checksum = 0; + int i; + + BUG_ON (p->output_buf_size + 3 >= GDB_BUFMAX); + BUG_ON (p->output_buf[start] != '$'); + + for (i=start+1; ioutput_buf_size; i++) + checksum += p->output_buf[i]; + + p->output_buf[p->output_buf_size++] = '#'; + p->output_buf[p->output_buf_size++] = hex[(checksum & 0xf0) >> 4]; + p->output_buf[p->output_buf_size++] = hex[(checksum & 0x0f) >> 0]; +} + + +/* Add a complete packet payload to the output queue. */ +static void push_output_packet (struct gdb_connection *p, const char *s) +{ + size_t ss = strlen(s); + size_t start; + int i; + + start = push_output_packet_start(p); + for (i=0; idata; + pr_debug ("report_quiesce %d event 0x%lx 0x%x->0x%x\n", task->pid, + event, action, p->at_quiesce_do); + + return p->at_quiesce_do; +} + + +u32 gdb_utrace_report_clone(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) +{ + pr_debug ("report_clone %d->%d\n", parent->pid, child->pid); + + if (clone_flags & CLONE_THREAD) { + printk (KERN_WARNING "unsupported multithreading on /proc/%d/gdb.\n", + task_pid_nr (parent)); + } + /* XXX: is there anything else to do here? */ + return UTRACE_RESUME; +} + + +u32 gdb_utrace_report_exec(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + /* XXX: Model an exec as if it were an exit. */ + struct gdb_connection *p = engine->data; + + pr_debug ("report_exec %d->%s\n", task->pid, task->comm); + + mutex_lock(&p->output_mutex); + + p->at_quiesce_do = UTRACE_STOP; + snprintf (p->stopcode, GDB_BUFMAX, "W%02x", 0); + push_output_packet (p, p->stopcode); + + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); + + /* Suspend the exec operation, to ensure that the connected gdb + receives the notification packet, and lets us go. */ + return UTRACE_STOP; +} + + +u32 gdb_utrace_report_signal(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka) +{ + struct gdb_connection *p = engine->data; + u32 ret = action; + int kern_p; + + mutex_lock(&p->output_mutex); + + kern_p = (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))); + + pr_debug ("report_signal %d (0x%x) kern %d skip %d stop %d\n", + task->pid, action, kern_p, p->skip_signals, p->stop_signals); + + /* The target is about to receive a signal. There are several + * cases: + * + * 1) This is an ordinary signal. We UTRACE_STOP to notify gdb. + * + * 2) This is a SIGTRAP arising from a breakpoint. We UTRACE_STOP. + * + * 3) This is a signal our code injected to stop the process, in lieu + * of UTRACE_INTERRUPT. We UTRACE_STOP | UTRACE_SIGNAL_IGN. + * + * 4) This is a signal our code injected on behalf of gdb (C/S/I packets). + * We UTRACE_RESUME. + * + * 5) This is a UTRACE_SIGNAL_REPORT or UTRACE_SIGNAL_HANDLER event. + * Just let utrace continue, as these signal events of minor internal + * interest. + */ + + if (utrace_signal_action(action) == UTRACE_SIGNAL_REPORT || + utrace_signal_action(action) == UTRACE_SIGNAL_HANDLER) { /* case 5 */ + /* NB: disregard p->at_quiesce_do */ + ret = UTRACE_RESUME | utrace_signal_action(action); + } else if (p->skip_signals > 0 /*&& kern_p*/) { /* case 4 */ + p->skip_signals --; + p->at_quiesce_do = UTRACE_RESUME; + ret = UTRACE_RESUME; /* deliver */ + } else if (p->stop_signals > 0 /*&& kern_p*/) { /* Case 3 */ + p->stop_signals --; + snprintf (p->stopcode, GDB_BUFMAX, "S%02x", info->si_signo); + push_output_packet (p, p->stopcode); + p->at_quiesce_do = UTRACE_STOP; + ret = UTRACE_STOP | UTRACE_SIGNAL_IGN; + } else { /* Cases 1, 2 */ + snprintf (p->stopcode, GDB_BUFMAX, "S%02x", info->si_signo); + push_output_packet (p, p->stopcode); + p->at_quiesce_do = UTRACE_STOP; + ret = UTRACE_STOP; + } + + pr_debug ("action 0x%x\n", ret); + + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); + + return ret; +} + + +u32 gdb_utrace_report_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + long orig_code, long *code) +{ + struct gdb_connection *p = engine->data; + + pr_debug ("report_exit %d (%lx)\n", task->pid, (unsigned long) orig_code); + + mutex_lock(&p->output_mutex); + + p->at_quiesce_do = UTRACE_STOP; + snprintf (p->stopcode, GDB_BUFMAX, + "W%02x", (unsigned)(orig_code & 0xFF)); + push_output_packet (p, p->stopcode); + + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); + + /* Suspend the exit operation, to ensure that the connected gdb + receives the notification packet, and lets us go. */ + return UTRACE_STOP; +} + + +u32 gdb_utrace_report_death(struct utrace_engine *engine, + struct task_struct *task, + bool group_dead, int signal) +{ + struct gdb_connection *p = engine->data; + + pr_debug ("report_death %d (%d)\n", task->pid, signal); + + mutex_lock(&p->output_mutex); + + p->at_quiesce_do = UTRACE_DETACH; + snprintf (p->stopcode, GDB_BUFMAX, "X%2x", (unsigned)(signal & 0xFF)); + push_output_packet (p, p->stopcode); + + p->engine = NULL; + + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); + + return UTRACE_DETACH; +} + + + +static const struct utrace_engine_ops gdb_utrace_ops = { + .report_quiesce = gdb_utrace_report_quiesce, + .report_signal = gdb_utrace_report_signal, + .report_death = gdb_utrace_report_death, + .report_exit = gdb_utrace_report_exit, + .report_exec = gdb_utrace_report_exec, + .report_clone = gdb_utrace_report_clone, + /* XXX: syscall trapping is also possible. */ +}; + + + +/* XXX: arch-dependent lookup of gdb remote protocol register + * numbering. The register numbers (user-side) & expected sizes come + * from gdb's regformats/FOO-linux.dat. The regset (kernel-side) + * numbers could come from offsetof/sizeof constructs based upon each + * arch's asm/user*.h. + */ + +struct gdb_map_regset { + unsigned pos; /* regset offset */ + unsigned count; /* regset byte count */ + unsigned rsn; /* regset number */ + unsigned bytes; /* gdb's view of register width; <= count */ +}; + +struct gdb_map_regset arch_i386_map_regset[] = { + [0]={ /* eax */ 6*4, 4, NT_PRSTATUS, 4, }, + [1]={ /* ecx */ 1*4, 4, NT_PRSTATUS, 4, }, + [2]={ /* edx */ 2*4, 4, NT_PRSTATUS, 4, }, + [3]={ /* ebx */ 0*4, 4, NT_PRSTATUS, 4, }, + [4]={ /* esp */ 15*4, 4, NT_PRSTATUS, 4, }, + [5]={ /* ebp */ 5*4, 4, NT_PRSTATUS, 4, }, + [6]={ /* esi */ 3*4, 4, NT_PRSTATUS, 4, }, + [7]={ /* edi */ 4*4, 4, NT_PRSTATUS, 4, }, + [8]={ /* eip */ 12*4, 4, NT_PRSTATUS, 4, }, + [9]={ /* eflags */ 14*4, 4, NT_PRSTATUS, 4, }, + [10]={ /* cs */ 13*4, 4, NT_PRSTATUS, 4, }, + [11]={ /* ss */ 16*4, 4, NT_PRSTATUS, 4, }, + [12]={ /* ds */ 7*4, 4, NT_PRSTATUS, 4, }, + [13]={ /* es */ 8*4, 4, NT_PRSTATUS, 4, }, + [14]={ /* fs */ 9*4, 4, NT_PRSTATUS, 4, }, + [15]={ /* gs */ 10*4, 4, NT_PRSTATUS, 4, }, + [16]={ /* st0 */ 0, 0, NT_PRFPREG, 10, }, + [17]={ /* st1 */ 0, 0, NT_PRFPREG, 10, }, + [18]={ /* st2 */ 0, 0, NT_PRFPREG, 10, }, + [19]={ /* st3 */ 0, 0, NT_PRFPREG, 10, }, + [20]={ /* st4 */ 0, 0, NT_PRFPREG, 10, }, + [21]={ /* st5 */ 0, 0, NT_PRFPREG, 10, }, + [22]={ /* st6 */ 0, 0, NT_PRFPREG, 10, }, + [23]={ /* st7 */ 0, 0, NT_PRFPREG, 10, }, + [24]={ /* fctrl */ 0, 0, NT_PRFPREG, 4, }, + [25]={ /* fstat */ 0, 0, NT_PRFPREG, 4, }, + [26]={ /* ftag */ 0, 0, NT_PRFPREG, 4, }, + [27]={ /* fiseg */ 0, 0, NT_PRFPREG, 4, }, + [28]={ /* fioff */ 0, 0, NT_PRFPREG, 4, }, + [29]={ /* foseg */ 0, 0, NT_PRFPREG, 4, }, + [30]={ /* fooff */ 0, 0, NT_PRFPREG, 4, }, + [31]={ /* fop */ 0, 0, NT_PRFPREG, 4, }, + [32]={ /* xmm0 */ 0, 0, NT_PRFPREG, 16, }, + [33]={ /* xmm1 */ 0, 0, NT_PRFPREG, 16, }, + [34]={ /* xmm2 */ 0, 0, NT_PRFPREG, 16, }, + [35]={ /* xmm3 */ 0, 0, NT_PRFPREG, 16, }, + [36]={ /* xmm4 */ 0, 0, NT_PRFPREG, 16, }, + [37]={ /* xmm5 */ 0, 0, NT_PRFPREG, 16, }, + [38]={ /* xmm6 */ 0, 0, NT_PRFPREG, 16, }, + [39]={ /* xmm7 */ 0, 0, NT_PRFPREG, 16, }, + [40]={ /* mxcsr */ 0, 0, NT_PRFPREG, 4, }, + [41]={ /* orig_eax*/ 0, 0, NT_PRSTATUS, 4, }, +}; + + +struct gdb_map_regset arch_x86_64_map_regset[] = { + [0]={ /* rax */ 10*8, 8, NT_PRSTATUS, 8, }, + [1]={ /* rbx */ 5*8, 8, NT_PRSTATUS, 8, }, + [2]={ /* rcx */ 11*8, 8, NT_PRSTATUS, 8, }, + [3]={ /* rdx */ 12*8, 8, NT_PRSTATUS, 8, }, + [4]={ /* rsi */ 13*8, 8, NT_PRSTATUS, 8, }, + [5]={ /* rdi */ 14*8, 8, NT_PRSTATUS, 8, }, + [6]={ /* rbp */ 4*8, 8, NT_PRSTATUS, 8, }, + [7]={ /* rsp */ 19*8, 8, NT_PRSTATUS, 8, }, + [8]={ /* r8 */ 9*8, 8, NT_PRSTATUS, 8, }, + [9]={ /* r9 */ 8*8, 8, NT_PRSTATUS, 8, }, + [10]={ /* r10 */ 7*8, 8, NT_PRSTATUS, 8, }, + [11]={ /* r11 */ 6*8, 8, NT_PRSTATUS, 8, }, + [12]={ /* r12 */ 3*8, 8, NT_PRSTATUS, 8, }, + [13]={ /* r13 */ 2*8, 8, NT_PRSTATUS, 8, }, + [14]={ /* r14 */ 1*8, 8, NT_PRSTATUS, 8, }, + [15]={ /* r15 */ 0*8, 8, NT_PRSTATUS, 8, }, + [16]={ /* rip */ 16*8, 8, NT_PRSTATUS, 8, }, + [17]={ /* flags */ 18*8, 8, NT_PRSTATUS, 4, }, + [18]={ /* cs */ 17*8, 8, NT_PRSTATUS, 4, }, + [19]={ /* ss */ 20*8, 8, NT_PRSTATUS, 4, }, + [20]={ /* ds */ 23*8, 8, NT_PRSTATUS, 4, }, + [21]={ /* es */ 24*8, 8, NT_PRSTATUS, 4, }, + [22]={ /* fs */ 25*8, 8, NT_PRSTATUS, 4, }, + [23]={ /* gs */ 26*8, 8, NT_PRSTATUS, 4, }, + [24]={ /* st0 */ 0, 0, NT_PRFPREG, 10, }, + [25]={ /* st1 */ 0, 0, NT_PRFPREG, 10, }, + [26]={ /* st2 */ 0, 0, NT_PRFPREG, 10, }, + [27]={ /* st3 */ 0, 0, NT_PRFPREG, 10, }, + [28]={ /* st4 */ 0, 0, NT_PRFPREG, 10, }, + [29]={ /* st5 */ 0, 0, NT_PRFPREG, 10, }, + [30]={ /* st6 */ 0, 0, NT_PRFPREG, 10, }, + [31]={ /* st7 */ 0, 0, NT_PRFPREG, 10, }, + [32]={ /* fctrl */ 0, 0, NT_PRFPREG, 4, }, + [33]={ /* fstat */ 0, 0, NT_PRFPREG, 4, }, + [34]={ /* ftag */ 0, 0, NT_PRFPREG, 4, }, + [35]={ /* fiseg */ 0, 0, NT_PRFPREG, 4, }, + [36]={ /* fioff */ 0, 0, NT_PRFPREG, 4, }, + [37]={ /* foseg */ 0, 0, NT_PRFPREG, 4, }, + [38]={ /* fooff */ 0, 0, NT_PRFPREG, 4, }, + [39]={ /* fop */ 0, 0, NT_PRFPREG, 4, }, + [40]={ /* xmm0 */ 0, 0, NT_PRFPREG, 16, }, + [41]={ /* xmm1 */ 0, 0, NT_PRFPREG, 16, }, + [42]={ /* xmm2 */ 0, 0, NT_PRFPREG, 16, }, + [43]={ /* xmm3 */ 0, 0, NT_PRFPREG, 16, }, + [44]={ /* xmm4 */ 0, 0, NT_PRFPREG, 16, }, + [45]={ /* xmm5 */ 0, 0, NT_PRFPREG, 16, }, + [46]={ /* xmm6 */ 0, 0, NT_PRFPREG, 16, }, + [47]={ /* xmm7 */ 0, 0, NT_PRFPREG, 16, }, + [48]={ /* xmm8 */ 0, 0, NT_PRFPREG, 16, }, + [49]={ /* xmm9 */ 0, 0, NT_PRFPREG, 16, }, + [50]={ /* xmm10 */ 0, 0, NT_PRFPREG, 16, }, + [51]={ /* xmm11 */ 0, 0, NT_PRFPREG, 16, }, + [52]={ /* xmm12 */ 0, 0, NT_PRFPREG, 16, }, + [53]={ /* xmm13 */ 0, 0, NT_PRFPREG, 16, }, + [54]={ /* xmm14 */ 0, 0, NT_PRFPREG, 16, }, + [55]={ /* xmm15 */ 0, 0, NT_PRFPREG, 16, }, + [56]={ /* mxcsr */ 0, 0, NT_PRFPREG, 4, }, + [57]={ /* orig_rax*/ 15*8, 8, NT_PRSTATUS, 8, }, +}; + + + +static int gdb_remote_register_info(struct gdb_connection *p, + struct task_struct *task, + unsigned number, + unsigned *pos, unsigned *count, + unsigned *bytes) +{ + const struct user_regset_view *rs = task_user_regset_view(task); + int rsn = -1; + + if(rs == 0) + return -ENOENT; + + /* pr_debug ("gdb_remote_register_info rs=%p rs->n=%u\n", rs, rs->n); */ + +#define GMRSIZE (sizeof(struct gdb_map_regset)) + + if(rs->e_machine == EM_386) { + if (number < sizeof(arch_i386_map_regset)/GMRSIZE) { + *pos = arch_i386_map_regset[number].pos; + *count = arch_i386_map_regset[number].count; + *bytes = arch_i386_map_regset[number].bytes; + rsn = arch_i386_map_regset[number].rsn; + } + } else if(rs->e_machine == EM_X86_64) { + if (number < sizeof(arch_x86_64_map_regset)/GMRSIZE) { + *pos = arch_x86_64_map_regset[number].pos; + *count = arch_x86_64_map_regset[number].count; + *bytes = arch_x86_64_map_regset[number].bytes; + rsn = arch_x86_64_map_regset[number].rsn; + } + } /* else ... rsn stays -1. */ + +#undef GMRSIZE + + /* Now map to the per-architecture regset index, based on the + elf core_note_type we found. */ + if (rsn >= 0) { + unsigned j; + for(j=0; jn; j++) { + if(rs->regsets[j].core_note_type == rsn) + return j; + } + } + + /* Invalid machines, register numbers, rsns, or unset rsns all + * fall through here. + */ + return -ENOENT; +} + + + +/* Process an entire, checksum-confirmed $command# at the front of + * p->input_buf[]. The input and output mutexes are being held. + */ +static void handle_gdb_command_packet (struct gdb_connection *p, struct task_struct *task) +{ + unsigned long arg1, arg2, arg3; + size_t op_start; + int rc = 0; + int i, j; + + pr_debug ("gdb packet code %c\n", p->input_buf[1]); + + switch (p->input_buf[1]) { + case '?': + if (p->at_quiesce_do != UTRACE_STOP) { + /* shouldn't happen */ + send_sig(SIGTRAP, task, 1); +#if 0 + rc = utrace_control (task, p->engine, UTRACE_INTERRUPT); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); +#endif + + /* Note that we don't enqueue a reply packet here, + but make gdb wait for a response from the + utrace report_FOO callbacks. */ + p->skip_signals ++; + } else { + push_output_packet (p, p->stopcode); + } + break; + + case 'i': /* [ADDR[,NNN]] */ + case 's': /* [ADDR] */ + /* XXX: if !arch_has_single_step() ... then what? */ + case 'c': /* [ADDR] */ + rc = sscanf(& p->input_buf[2], "%lx,%lx", &arg1, &arg2); + if (rc >= 1) { /* Have a PC? */ + /* XXX: set it */ + } + if (rc >= 2) { /* ,NNN present */ + /* XXX: disregard it. */ + } + /* XXX: args ignored */ + p->stopcode[0]='\0'; + p->at_quiesce_do = + ((p->input_buf[1]=='c' || !arch_has_single_step()) + ? UTRACE_RESUME : UTRACE_SINGLESTEP); + if (p->at_quiesce_do == UTRACE_SINGLESTEP) + p->stop_signals ++; + utrace_control (task, p->engine, p->at_quiesce_do); + break; + case 'C': /* SIG[;ADDR] */ + case 'S': /* SIG[;ADDR] */ + /* XXX: if !arch_has_single_step() ... then what? */ + case 'I': /* SIG[;ADDR[,NNN?]] */ + rc = sscanf(& p->input_buf[2], "%lx;%lx,%lx", &arg1, &arg2, &arg3); + if (rc >= 1) { /* SIG present */ + send_sig ((int)arg1, task, 1); + } + if (rc >= 2) { /* ;ADDR present */ + /* XXX: not done */ + } + if (rc >= 3) { /* ,NNN present */ + /* XXX: disregard it. */ + } + p->skip_signals ++; + p->stopcode[0]='\0'; + p->at_quiesce_do = + ((p->input_buf[1]=='C' || !arch_has_single_step()) + ? UTRACE_RESUME : UTRACE_SINGLESTEP); + if (p->at_quiesce_do == UTRACE_SINGLESTEP) + p->stop_signals ++; + utrace_control (task, p->engine, p->at_quiesce_do); + /* Response will come at next report_signal. */ + break; + case 'D': + push_output_packet (p, "OK"); + /* NB: the .release fop callback performs actual utrace detach. */ + break; + case 'g': + op_start = push_output_packet_start(p); + /* GDB_BUFMAX stands for some random large number, + * known to be larger than the number of gdb indexed + * registers. */ + for (i=0; i 0 && rs_count < bytes); + /* Assert reg_contents size is right. */ + BUG_ON(sizeof(reg_contents) < bytes || + sizeof(reg_contents) < rs_count); + + if (rs_count) { /* real register */ + rsv = task_user_regset_view(task); + BUG_ON(rsn >= rsv->n); + rs = & rsv->regsets[rsn]; + + /* Extract the register value into reg_contents[]. */ + rc = (rs->get) (task, rs, rs_pos, rs_count, + reg_contents, NULL); + if (rc) + break; + } else { /* dummy value */ + memset (reg_contents, 0, sizeof(reg_contents)); + } + + /* Hex-dump it. */ + /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u (", + i, rsn, rs_pos, rs_count, bytes); */ + /* XXX: endianness adjust for count != bytes */ + for(j=0; jinput_buf[op_start] != '#' && + op_start < p->input_buf_size) { + unsigned rs_count; + unsigned rs_pos; + unsigned bytes; + const struct user_regset_view* rsv; + const struct user_regset* rs; + unsigned char reg_contents[16]; /* maximum reg. width */ + + int rsn = gdb_remote_register_info(p, task, i, + &rs_pos, &rs_count, + &bytes); + /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u\n", + i, rsn, rs_pos, rs_count, bytes); */ + + if (rsn < 0) + break; + + /* If we want to extract register data, make sure + we're fetching at least that much. */ + BUG_ON(rs_count > 0 && rs_count < bytes); + /* Assert reg_contents size is right. */ + BUG_ON(sizeof(reg_contents) < bytes || + sizeof(reg_contents) < rs_count); + + /* Remaining packet too short? */ + if ((op_start + 2*bytes + 3) < p->input_buf_size) + break; + + /* 0-fill the register copy. XXX initialize + * it from rs->get() instead? + */ + memset (reg_contents, 0, sizeof(reg_contents)); + + /* Hex-unconvert all the bytes. */ + /* XXX: endianness adjust for count != bytes */ + for(j=0; jinput_buf[op_start+2*j], + p->input_buf[op_start+2*j+1]); + op_start += 2*bytes; + + if (rs_count) { /* real register */ + BUG_ON(rs_count > sizeof(reg_contents)); + rsv = task_user_regset_view(task); + BUG_ON(rsn >= rsv->n); + rs = & rsv->regsets[rsn]; + + /* Set the register value from reg_contents[]. */ + rc = (rs->set) (task, rs, rs_pos, rs_count, + reg_contents, NULL); + if (rc) + break; + } else { /* dummy register */ + ; + } + } + if (p->input_buf[op_start] == '#' && rc == 0) + push_output_packet (p, "OK"); + else + push_output_packet (p, "E01"); + break; + case 'p': /* REG */ + break; + case 'P': /* REG=VAL */ + break; + case 'm': /* ADDR,LENGTH */ + rc = sscanf(& p->input_buf[2], "%lx,%lx", &arg1, &arg2); + if (rc != 2) + push_output_packet(p, "E01"); + else { + size_t o = push_output_packet_start (p); + while (arg2 > 0) { + unsigned char value; + + /* Simply stop looping if requested + length was too large. gdb will + probably retry from this point + on. */ + if (p->output_buf_size + 5 > GDB_BUFMAX) + break; + + rc = access_process_vm(task, arg1, &value, 1, 0); + if (rc != 1) + break; /* EFAULT */ + else + push_output_hex (p, value); + + arg1++; + arg2--; + } + push_output_packet_end (p, o); + } + break; + case 'M': /* ADDR,LENGTH:XX */ + /* `i' will index p->input_buf to consume XX hex bytes. */ + rc = sscanf(& p->input_buf[2], "%lx,%lx:%n", + &arg1, &arg2, &i); + op_start = i + 2; /* Skip the leading $M also. */ + if (rc < 2) { + push_output_packet(p, "E01"); + break; + } + while (arg2 > 0) { + unsigned char value; + + /* Check that enough input bytes left for + * these two hex chars, plus the #XX checksum. + */ + if (i+4 >= p->input_buf_size) + break; + + value = byteme(p->input_buf[i], + p->input_buf[i+1]); + rc = access_process_vm(task, arg1, &value, 1, 1); + if (rc != 1) + break; /* EFAULT */ + + i += 2; + arg1++; + arg2--; + } + if (arg2 != 0) + push_output_packet(p, "E02"); + else + push_output_packet(p, "OK"); + break; + default: + push_output_packet (p, ""); + } +} + + + + +/* ------------------------------------------------------------------------ */ + +/* gdb control callbacks */ + +#define get_proc_task(inode) get_pid_task(PROC_I((inode))->pid, PIDTYPE_PID) + +static int proc_gdb_open(struct inode *inode, struct file *filp) +{ + struct task_struct *task = get_proc_task(inode); + int ret = -EBUSY; + struct gdb_connection *p; + struct list_head *l; + + pr_debug ("opened /proc/%d/gdb\n", task->pid); + + /* Reject kernel threads. */ + if (task->flags & PF_KTHREAD) { + ret = -EINVAL; + goto out; + } + + /* Reject if connection is for other than tg-leader thread. */ + if (task_pid_nr(task) != task_tgid_nr(task)) { + ret = -EINVAL; + goto out; + } + + mutex_lock (& gdb_connections_mutex); + + /* Reject if a connection exists for the thread group + * leader. + */ + list_for_each(l, &gdb_connections) { + p = list_entry (l, struct gdb_connection, link); + if (p->target == task_tgid_nr(task)) { + ret = -EBUSY; + goto out_mutex; + } + } + /* (Don't unlock yet, to defeat a race of two concurrent opens.) */ + + p = kzalloc(sizeof (struct gdb_connection), GFP_KERNEL); + if (!p) { + ret = -ENOMEM; + goto out_mutex; + } + + /* Send initial ping to gdb. */ + push_output_packet (p, ""); + + mutex_init(& p->output_mutex); + init_waitqueue_head(& p->output_wait); + + mutex_init(& p->input_mutex); + init_waitqueue_head(& p->input_wait); + + p->target = task->tgid; + + /* NB: During attach, we don't want to bother the target. + Soon though a send_sig will interrupt it. */ + p->at_quiesce_do = UTRACE_RESUME; + + p->engine = utrace_attach_task(task, + UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE, + &gdb_utrace_ops, + p); + if (IS_ERR(p->engine) || p->engine==NULL) { + ret = -EINVAL; + goto out_free; + } + + ret = utrace_set_events(task, p->engine, + UTRACE_EVENT_SIGNAL_ALL| + UTRACE_EVENT(QUIESCE)| + UTRACE_EVENT(DEATH)| + UTRACE_EVENT(EXIT)| + UTRACE_EVENT(EXEC)| + UTRACE_EVENT(CLONE)); + pr_debug ("utrace_set_events sent, ret=%d\n", ret); + if (!ret) + ; + + filp->private_data = p; + + INIT_LIST_HEAD(& p->link); + list_add(&gdb_connections, &p->link); + + p->stop_signals ++; + send_sig(SIGTRAP, task, 1); +#if 0 + ret = utrace_control(task, p->engine, UTRACE_INTERRUPT); + if (ret == -EINPROGRESS) + ret = utrace_barrier(task, p->engine); +#endif + + goto out_mutex; + +out_free: + kfree(p); +out_mutex: + mutex_unlock (& gdb_connections_mutex); +out: + return ret; +} + + +static int proc_gdb_release(struct inode *inode, struct file *filp) +{ + struct task_struct *task = get_proc_task(inode); + struct gdb_connection *p = filp->private_data; + int ret = 0; + + mutex_lock (& gdb_connections_mutex); + + if (task == NULL) { + /* The thread is already gone; report_death was already called. */ + pr_debug ("gdb %d releasing old\n", p->target); + } else { + pr_debug ("gdb %d releasing current\n", p->target); + + ret = utrace_set_events(task, p->engine, 0); + if (ret == -EINPROGRESS) + ret = utrace_barrier(task, p->engine); + /* No more callbacks will be received! */ + + ret = utrace_control(task, p->engine, UTRACE_DETACH); /* => RESUME */ + if (ret == -EINPROGRESS) + ret = utrace_barrier(task, p->engine); + + utrace_engine_put (p->engine); + } + + list_del(&p->link); + kfree(p); + + mutex_unlock (& gdb_connections_mutex); + + return ret; +} + + + +static int proc_gdb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + /* XXX: GDB usually thinks that a file name for "target + * remote" implies a serial port with tty-ish ioctl's + * available. We pretend to accept them all. */ + return 0; +} + + + +static ssize_t proc_gdb_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + struct gdb_connection *p = filp->private_data; + struct task_struct *task; + int rc = 0; + size_t len; + + task = find_task_by_vpid (p->target); + if (!task) + return -EINVAL; + + if ((p->output_buf_size <= p->output_buf_read) && + filp->f_flags & O_NONBLOCK) + return -EAGAIN; + +again: + rc = wait_event_interruptible (p->output_wait, + (p->output_buf_size > p->output_buf_read)); + if (rc) + goto out; + + mutex_lock(&p->output_mutex); + + if(p->output_buf_size <= p->output_buf_read) { + mutex_unlock(&p->output_mutex); + goto again; + } + + len = min (count, (size_t)(p->output_buf_size - p->output_buf_read)); + if (copy_to_user (buf, & p->output_buf[p->output_buf_read], len)) { + rc = -EFAULT; + goto out_unlock; + } + + pr_debug ("sent %u bytes (%ld left) data (%.*s)\n", + (unsigned)len, + ((long)p->output_buf_size-(long)p->output_buf_read)-len, + (int)len, & p->output_buf[p->output_buf_read]); + + p->output_buf_read += len; + rc = len; + + /* If whole packet is consumed, reset for next one. */ + BUG_ON (p->output_buf_read > p->output_buf_size); + if (p->output_buf_read == p->output_buf_size) { + p->output_buf_read = 0; + p->output_buf_size = 0; + } + +out_unlock: + mutex_unlock(&p->output_mutex); + +out: + return rc; +} + + +static ssize_t proc_gdb_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct gdb_connection *p = filp->private_data; + size_t last_input_buf_size; + struct task_struct *task; + size_t len; + int ret = 0; + + task = find_task_by_vpid (p->target); + if (!task) + return -EINVAL; + +again: + ret = wait_event_interruptible (p->input_wait, + (p->input_buf_size < GDB_BUFMAX)); + if (ret) + goto out; + + mutex_lock(&p->input_mutex); + if (p->input_buf_size == GDB_BUFMAX) { + mutex_unlock(&p->input_mutex); + goto again; + } + mutex_lock(&p->output_mutex); + + /* We now know there is some room in the input buffer. Upon + entry, the input_buf will either be empty, or contain a + partial gdb request packet. */ + + /* Copy the data. */ + len = min (count, (size_t)(GDB_BUFMAX - p->input_buf_size)); + if (copy_from_user (& p->input_buf[p->input_buf_size], buf, len)) { + ret = -EFAULT; + goto out_unlock; + } + + /* pr_debug ("received data %.*s\n", (int)len, & p->input_buf[p->input_buf_size]); */ + + p->input_buf_size += len; + ret = len; + + /* Process any packets in the buffer to restore the incoming + invariant. (Normal GDB will not send more than one packet + before waiting for a response.) */ + + /* We iterate until we can no longer shrink the input buffer. Usually + we will not iterate more than once, since there may be one +/- + ack byte and/or one gdb packet. */ + last_input_buf_size = 0; + while (p->input_buf_size + && p->input_buf_size != last_input_buf_size) { + last_input_buf_size = p->input_buf_size; + + if (p->input_buf[0] == '+') { + /* This must have been an ack to our + * previously output packet. + * Consume the input. + */ + memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); + } else if (p->input_buf[0] == '-') { + /* Whoops, a nak. Unfortunately, we don't + * handle transmission errors by + * retransmitting the last output_buf; it's + * already gone. OTOH we should not encounter + * transmission errors on a reliable channel + * such as a read syscall. + * Consume the input. + */ + printk(KERN_WARNING "Unexpected NAK received" + "on /proc/%d/gdb connection.\n", task_pid_nr(task)); + memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); + } else if (p->input_buf[0] == 3) { /* ^C == INTR */ + /* NB: don't overwrite 'ret'. */ + pr_debug ("received gdb interrupt\n"); + p->stop_signals ++; + send_sig(SIGTRAP, task, 1); +#if 0 + int rc = utrace_control(task, p->engine, UTRACE_INTERRUPT); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); +#endif + /* p->at_quiesce_do will be set in report_signal(SIGNAL_REPORT) */ + /* NB: this packet does not generate an +/- ack. + Consume the input. */ + memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); + } else if (p->input_buf[0] == '$') { /* command packet */ + int j; + unsigned char checksum = 0; + for (j=1; jinput_buf_size-2; j++) { + if (p->input_buf[j] == '#') { + unsigned char checksum2; + checksum2 = byteme (p->input_buf[j+1], + p->input_buf[j+2]); + pr_debug ("received gdb packet %.*s\n", + j+3, & p->input_buf[0]); + if (checksum == checksum2) { + push_output (p, '+'); + handle_gdb_command_packet (p, task); + } else { + push_output (p, '-'); + } + /* Consume the whole packet. */ + p->input_buf_size -= (j+3); + memmove(&p->input_buf[0], &p->input_buf[j+3], + p->input_buf_size); + break; + } else { + checksum += p->input_buf[j]; + } + } /* End searching for end of packet */ + + /* We may not have found the # + * checksum. If so, leave the partial packet + * in input_buf. Since input_buf_size will + * not have decreased, the while() loop above + * will detect a fixpoint and exit. + * + * Alternately, there could be another gdb packet + * just behind the one we just consumed. In this + * we'll iterate one more time in this loop. + */ + } else { /* junk character */ + printk(KERN_WARNING "Unexpected character (%x) received" + " on /proc/%d/gdb connection.\n", + (int) p->input_buf[0], task_pid_nr(task)); + /* Consume the input. */ + memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); + } + } + +out_unlock: + wake_up(&p->input_wait); /* Probably have more room in input_buf. */ + wake_up(&p->output_wait); /* Probably have data in output_buf. */ + + mutex_unlock(&p->output_mutex); + mutex_unlock(&p->input_mutex); +out: + return ret; +} + + +const struct file_operations proc_gdb_operations = { + .open = proc_gdb_open, + .read = proc_gdb_read, + .write = proc_gdb_write, + .release = proc_gdb_release, + .ioctl = proc_gdb_ioctl, +}; + + From contact at onedirect.ccemails.com Tue Jul 7 08:11:10 2009 From: contact at onedirect.ccemails.com (Onedirect) Date: Tue, 7 Jul 2009 10:11:10 +0200 (CEST) Subject: =?iso-8859-15?q?5_offres_exceptionnelles_=E0_ne_pas_rater?= Message-ID: <31155884909.5773361.1246954270339@schr3> Bonjour, si vous n'arrivez pas à lire ce message, visualisez la version en ligne : http://trc1.emv2.com/HM?a=A9X7Cq5nhCKC8XglAayrvYbkXw. Vous recevez ce courriel sur l'adresse utrace-devel at redhat.com. Pour être sûr de recevoir correctement nos courriels, ajoutez l'adresse caroline at onedirect.fr à votre carnet d'adresse. Découvrez toute la gamme de téléphonie pro : http://trc1.emv2.com/HU?a=A9X7Cq5nhCKC8XglAayrvYXkUg Casque, Kit Bluetooth, Téléphone sans fil, Téléphone filaire, Mini-standard, Talkie Walkie, Téléconférence, Enregistreurs. Une équipe formée et disponible vous conseille. Plus de 100 000 clients nous font confiance depuis 1999, 1800 références en stock permanent. 96% des commandes expédiées le jour même. Appelez le 08 26 10 11 12 0,15ttc/mn Ce courriel commercial est conforme à la législation en vigueur et aux délibérations de la CNIL des 22 et 30 mars 2005 sur la prospection par courrier électronique dans le cadre professionnel. Conformément à l'article 34 de la loi 78-17 du 6 janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés, vous disposez d'un droit d'accès, de rectification des données nominatives vous concernant. Si vous ne souhaitez plus recevoir d'informations commerciales de notre société par e-mail, Désabonnez vous : http://trc1.emv2.com/HP?a=A9X7Cq5nhCKC8XglAayrvYfkUA. Le présent message est en parfait respect avec la déontologie et les bonnes pratiques de la communication par marketing direct électronique. Conformément à la législation en vigueur et des différents rectificatifs légaux, vous disposez d'un plein droit d'accès, de modifications ou de suppression des données personnelles vous concernant. Vous pouvez à tout moment excécer se droit sur demande écrite ou via notre espace prévu à cet effet. Conformément à la loi Informatique et libertés, vous pouvez vous désabonner à tout moment. Pour toute autre demande n'hésitez pas à nous écrire (Afin de faciliter le traitement de votre envoi, précisez votre demande dans l'objet et le corps du message). Loi n° 78-17 du 6 Janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une nécessité légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement de la publicité par voie électronique. Art 38 : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une obligation légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement. Cet e-mail vous a été envoyé par OneDirect qui peut être amenée à recourir à ses sociétés affiliées afin de vous fournir ses services. Vos préférences de notification indiquent que vous souhaitez recevoir des informations sur les promotions, les offres spéciales et certaines manifestations. OneDirect ne vous demandera JAMAIS de fournir par e-mail des informations personnelles telles que les mots de passe. Vous êtes inscrit(e) en utilisant l'adresse utrace-devel at redhat.com indiquée lors de votre inscription sur notre site. Si vous ne souhaitez plus recevoir de propositions commerciales de notre part, il vous suffit de vous rendre sur le site, et de changer vos préférences de notification par email à caroline at onedirect.fr. Copyright © 2008 OneDirect. Tous droits réservés. Les marques et marques commerciales mentionnées appartiennent à leurs propriétaires respectifs. -------------- next part -------------- An HTML attachment was scrubbed... URL: From info at soft-direct.net Tue Jul 7 14:52:40 2009 From: info at soft-direct.net (Ticket Restaurant par Soft Direct) Date: Tue, 7 Jul 2009 17:52:40 +0300 Subject: =?utf-8?q?Faim_de_convivialit=C3=A9=2C_soif_de_partage_=3F?= Message-ID: <7ee88616e5b0c3f208249c0d63269b3f@om2.market-products.com> An HTML attachment was scrubbed... URL: From velhaguarda at unidosdadoze.com.br Tue Jul 7 15:36:06 2009 From: velhaguarda at unidosdadoze.com.br (=?iso-8859-1?Q?UNIDOS_DA_DOZE_FC?=) Date: Tue, 07 Jul 2009 12:36:06 -0300 Subject: Projeto Velha Guarda - Samba de Raiz Message-ID: <200907071236060.258893001246980966@server7.aknamail000.com.br> Ol? , Este programa n?o permite a visualiza??o de mensagens formatadas (com cores, imagens e links), portanto solicitamos que voc? copie o texto abaixo, e cole no campo "Endere?o" do seu navegador. http://app.aknaemkt.com.br/emkt/tracer/?1,156707,1abeca64,99f8 Para garantir que nossas mensagens cheguem em sua caixa de entrada, adicione o email velhaguarda at unidosdadoze.com.br ao seu cat?logo de endere?os. N?o deseja mais receber nossas mensagens? Cancele sua inscri??o aqui: http://app.aknaemkt.com.br/emkt/tracer/?9,156707,1abeca64,99f8 -------------- next part -------------- An HTML attachment was scrubbed... URL: From fche at redhat.com Tue Jul 7 18:18:59 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Tue, 7 Jul 2009 14:18:59 -0400 Subject: documenting utrace callbacks better Message-ID: <20090707181859.GB1933@redhat.com> Hi - While hacking on the gdb stub thingie, I needed several irc talks with roland to understand what I was seeing. Some improved kerneldocs may help matters. Specifically ... - The report_signal callback's block of description is too dense. It would be better to discuss the REPORT and HANDLER cases separately, with respect to which input parameters are expected to be initialized, and what return action values are valid. Actually it would be nice for the overall signal handling process to be illustrated as a timing diagram, listing the sequence of calls that may arrive, and what actions at each stage may be typical. - The UTRACE_SINGLESTEP action appears to require setting up a quiesce callback echoing the utrace_control() request in order for it to become effective. (Without a quiesce, the singlestep request gets lost and turned into a resume or something.) The documentation suggests setting up such a callback "may be" needed, but actually it "is really" needed. - FChE From revealment at dms.mcw.gov.cy Tue Jul 7 21:49:24 2009 From: revealment at dms.mcw.gov.cy (Foulger Brucz) Date: Tue, 07 Jul 2009 22:49:24 +0100 Subject: Better sex Life - I Want too Improve Myy sex Life Message-ID: <45476714@dms.mcw.gov.cy> Better sex Life -- II Want to Improve My sex Life www. ko45. net. Figure skaater basnned after being stopped on moped From tianguanhua at ncic.ac.cn Thu Jul 9 00:54:54 2009 From: tianguanhua at ncic.ac.cn (tgh) Date: Thu, 9 Jul 2009 08:54:54 +0800 Subject: a question about process information In-Reply-To: <20090707042639.GC25935@redhat.com> References: <20090707042639.GC25935@redhat.com> Message-ID: <004601ca002f$df45b1b0$9dd11510$@ac.cn> hi I have a question about linux , I hear that linux2.6.27 provide information about resource usage for each process, such as, CPU, memory, I/O, and I want to know how to get it, does some proc or sysfs have these information ,or something else has it, or how to get it from systemtap Could you help me Thank you From teratogen at dospara.co.jp Thu Jul 9 02:12:47 2009 From: teratogen at dospara.co.jp (Ginard) Date: Thu, 09 Jul 2009 01:12:47 -0100 Subject: Small penis sex Tips - See How Easily You aCn Satisfy Her Witth a Small Member Message-ID: <058f36786520090709011131@dospara.co.jp> Small penis sex Tips - Svee How Esaily You Can Satisfy Her With a Small Member www. ba43. com. lAlleged store robber leaves his W-2 form From newsletter at usbportugal.com Thu Jul 9 03:52:05 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Thu, 9 Jul 2009 05:52:05 +0200 Subject: =?iso-8859-1?q?J=E1_n=E3o_h=E1_mem=F3ria_de=2E=2E=2ESemana_28?= Message-ID: <26a502b2e138bb7bb2c285abf4dac7a7@newsletter2.usbportugal.com> An HTML attachment was scrubbed... URL: From fabienne at busiboutique.net Thu Jul 9 07:58:30 2009 From: fabienne at busiboutique.net (=?windows-1252?Q?Fabienne_/_BusiBoutique?=) Date: Thu, 9 Jul 2009 09:58:30 +0200 Subject: =?windows-1252?q?Il_vous_fait_gagner_un_temps_pr=E9cieux=2E?= Message-ID: Facile ? installer, facile ? utiliser, Il vous fait gagner un temps pr?cieux ! Exclusivit? BusiBoutique.Com : livr? avec son chargeur automatique de documents. Le Multifonction PagePro 1380MF est dot? de consommables facilement rempla?ables et d'un bac papier grande capacit? de 250 feuilles. Il est fourni avec un logiciel qui num?rise et copie les images directement sur votre PC (valable jusqu'au 31 Juillet 2009) Konica Minolta PagePro 1380 MF le Multifonction ( Noir et blanc ) - Impression : 20 ppm au format A4 en monochrome - Copie : jusque 20 ppm au format A4 en monochrome - Impression : 600 x 600 ppp - Num?risation : 1 200 ppp en couleur - Premi?re page : 19 secondes - Liaison USB - avec Chargeur automatique de documents (50 feuilles) livr? bien sur avec ces consommables. Prix Incroyable ! seulement 99 TTC Cette offre est accessible sur le site, Oui je veux profiter imm?diatement de cette offre sp?ciale ! et ensuite, Konica Minolta vous rembourse 60 ? soit un co?t r?el pour vous au final de seulement 32,60 ? HT Comme d'habitude chez BusiBoutique.Com, en commandant aujourd'hui, vous recevez la livraison sous 24 ? 72 heures chez vous, (frais de port 8,50 HT) ou ? l'adresse de votre choix. A tout de suite, Pour b?n?ficier de cette offre, cliquez sur le lien ci-dessus ou contactez le Service Direct. par t?l?phone au 03 88 70 50 16 ou par email ? direct at busiboutique.com . Cette offre vous est r?serv?e, non cumulable et valable uniquement chez BusiBoutique.com, dans la limite des stocks disponibles. Attention, il n'y a que quelques machines disponibles !, les premiers arriv?s seront les premiers servis. Cordialement Fabienne du Service Direct Informatique FRIESS service BusiBoutique.Com 32, rue Principale 67270 ROHR Tel. 03 88 70 50 16 - Fax 03 88 70 54 10 site : www.busiboutique.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From contact at onedirect.ccemails.com Thu Jul 9 08:50:26 2009 From: contact at onedirect.ccemails.com (Motorola) Date: Thu, 9 Jul 2009 10:50:26 +0200 (CEST) Subject: =?iso-8859-15?q?TLKR_T7_=3A_le_compte_=E0_rebours_est_lanc=E9?= Message-ID: <31155884909.5783488.1247129426302@schr3> Bonjour, si vous n'arrivez pas à lire ce message, visualisez la version en ligne : http://trc1.emv2.com/HM?a=A9X7Cq5nhCKC8XgC8Kykrx3jZQ. Vous recevez ce courriel sur l'adresse utrace-devel at redhat.com. Pour être sûr de recevoir correctement nos courriels, ajoutez l'adresse caroline at onedirect.fr à votre carnet d'adresse. Découvrez toute la gamme de téléphonie pro : http://trc1.emv2.com/HU?a=A9X7Cq5nhCKC8XgC8KykrxDjmA Casque, Kit Bluetooth, Téléphone sans fil, Téléphone filaire, Mini-standard, Talkie Walkie, Téléconférence, Enregistreurs. Une équipe formée et disponible vous conseille. Plus de 100 000 clients nous font confiance depuis 1999, 1800 références en stock permanent. 96% des commandes expédiées le jour même. Appelez le 08 26 10 11 12 0,15ttc/mn Ce courriel commercial est conforme à la législation en vigueur et aux délibérations de la CNIL des 22 et 30 mars 2005 sur la prospection par courrier électronique dans le cadre professionnel. Conformément à l'article 34 de la loi 78-17 du 6 janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés, vous disposez d'un droit d'accès, de rectification des données nominatives vous concernant. Si vous ne souhaitez plus recevoir d'informations commerciales de notre société par e-mail, Désabonnez vous : http://trc1.emv2.com/HP?a=A9X7Cq5nhCKC8XgC8KykrxLjZg. Le présent message est en parfait respect avec la déontologie et les bonnes pratiques de la communication par marketing direct électronique. Conformément à la législation en vigueur et des différents rectificatifs légaux, vous disposez d'un plein droit d'accès, de modifications ou de suppression des données personnelles vous concernant. Vous pouvez à tout moment excécer se droit sur demande écrite ou via notre espace prévu à cet effet. Conformément à la loi Informatique et libertés, vous pouvez vous désabonner à tout moment. Pour toute autre demande n'hésitez pas à nous écrire (Afin de faciliter le traitement de votre envoi, précisez votre demande dans l'objet et le corps du message). Loi n° 78-17 du 6 Janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une nécessité légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement de la publicité par voie électronique. Art 38 : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une obligation légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement. Cet e-mail vous a été envoyé par OneDirect qui peut être amenée à recourir à ses sociétés affiliées afin de vous fournir ses services. Vos préférences de notification indiquent que vous souhaitez recevoir des informations sur les promotions, les offres spéciales et certaines manifestations. OneDirect ne vous demandera JAMAIS de fournir par e-mail des informations personnelles telles que les mots de passe. Vous êtes inscrit(e) en utilisant l'adresse utrace-devel at redhat.com indiquée lors de votre inscription sur notre site. Si vous ne souhaitez plus recevoir de propositions commerciales de notre part, il vous suffit de vous rendre sur le site, et de changer vos préférences de notification par email à caroline at onedirect.fr. Copyright © 2008 OneDirect. Tous droits réservés. Les marques et marques commerciales mentionnées appartiennent à leurs propriétaires respectifs. -------------- next part -------------- An HTML attachment was scrubbed... URL: From info at canal-direct.com Thu Jul 9 14:50:00 2009 From: info at canal-direct.com (=?ISO-8859-1?Q?Chlo=E9_DAUMAS?=) Date: Thu, 09 Jul 2009 16:50:00 +0200 Subject: Planning mural de gestion Message-ID: An HTML attachment was scrubbed... URL: From srikar at linux.vnet.ibm.com Thu Jul 9 15:42:53 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Thu, 9 Jul 2009 21:12:53 +0530 Subject: linux kernel gdb stub for userspace processes, prototype version 3 In-Reply-To: <20090707042639.GC25935@redhat.com> References: <20090707042639.GC25935@redhat.com> Message-ID: <20090709154253.GA8077@linux.vnet.ibm.com> Hi Frank, Current gdb stub seems to cause a SIGSTOP when a signal handler is called. And this behaviour is not consistent. This behaviour is different from when gdb was invoked on the program without the stap. I believe the STOP at signal handler would only happen when UTRACE_SIGNAL_HANDLER or UTRACE_SIGNAL_REPORT before the utrace-gdb quiesce handler gets called. The patch is as below. commit eb53493b0208bc036dc570560ac3449aed450fbf Author: Srikar Dronamraju Date: Thu Jul 9 21:03:45 2009 +0530 make sure quiesce doesnt make the process to stop at the signal handler diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index 3835761..cbed911 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -10,7 +10,7 @@ * Red Hat Author: Frank Ch. Eigler */ -/* #define DEBUG 1 */ +#define DEBUG 1 #include #include @@ -249,6 +249,7 @@ u32 gdb_utrace_report_signal(u32 action, if (utrace_signal_action(action) == UTRACE_SIGNAL_REPORT || utrace_signal_action(action) == UTRACE_SIGNAL_HANDLER) { /* case 5 */ /* NB: disregard p->at_quiesce_do */ + p->at_quiesce_do = UTRACE_RESUME; ret = UTRACE_RESUME | utrace_signal_action(action); } else if (p->skip_signals > 0 /*&& kern_p*/) { /* case 4 */ p->skip_signals --; > Hi - > > Further to http://sourceware.org/ml/systemtap/2009-q2/msg00969.html, I > attach another snapshot of my gdb-stub in linux-kernel prototype. It's > working a lot better. Usage is as before: > > % PROCESS & > [1] 21175 > % gdb PROCESS > (gdb) target remote /proc/21175/gdb > (gdb) # whatever strikes your fancy > > Known limitations: > - http://sourceware.org/ml/gdb/2009-07/msg00036.html > (occasional "Remote failure reply: E....." error) > - only for single-threaded programs > - x86-64 and x86 only > - floating poing registers not yet done > - checkpatch.pl not yet satisfied > > This patch should apply to recent utrace-patched kernels. > > - FChE > > > diff --git a/fs/proc/base.c b/fs/proc/base.c > index 3326bbf..0afb05a 100644 > --- a/fs/proc/base.c > +++ b/fs/proc/base.c > @@ -77,6 +77,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -2542,6 +2543,9 @@ static const struct pid_entry tgid_base_stuff[] = { > #ifdef CONFIG_TASK_IO_ACCOUNTING > INF("io", S_IRUGO, proc_tgid_io_accounting), > #endif > +#ifdef CONFIG_UTRACE_GDB > + REG("gdb", S_IRUSR|S_IWUSR, proc_gdb_operations), > +#endif > }; > > static int proc_tgid_base_readdir(struct file * filp, > diff --git a/include/linux/utrace.h b/include/linux/utrace.h > index f877ec6..f33a5da 100644 > --- a/include/linux/utrace.h > +++ b/include/linux/utrace.h > @@ -689,4 +689,8 @@ static inline __must_check int utrace_barrier_pid(struct pid *pid, > > #endif /* CONFIG_UTRACE */ > > +#ifdef CONFIG_UTRACE_GDB > +extern const struct file_operations proc_gdb_operations; > +#endif > + > #endif /* linux/utrace.h */ > diff --git a/init/Kconfig b/init/Kconfig > index a6987df..7ffa60d 100644 > --- a/init/Kconfig > +++ b/init/Kconfig > @@ -1158,6 +1158,14 @@ menuconfig UTRACE > kernel interface exported to kernel modules, to track events in > user threads, extract and change user thread state. > > +config UTRACE_GDB > + bool "/proc//gdb file for gdb remote connection" > + select UTRACE > + default y > + help > + Enable the utrace-based /proc//gdb process debugging > + interface, for connection using the gdb remote protocol. > + > source "block/Kconfig" > > config PREEMPT_NOTIFIERS > diff --git a/kernel/Makefile b/kernel/Makefile > index a79634e..21457e6 100644 > --- a/kernel/Makefile > +++ b/kernel/Makefile > @@ -69,6 +69,7 @@ obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o > obj-$(CONFIG_STOP_MACHINE) += stop_machine.o > obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o > obj-$(CONFIG_UTRACE) += utrace.o > +obj-$(CONFIG_UTRACE_GDB) += utrace-gdb.o > obj-$(CONFIG_AUDIT) += audit.o auditfilter.o > obj-$(CONFIG_AUDITSYSCALL) += auditsc.o > obj-$(CONFIG_AUDIT_TREE) += audit_tree.o > diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c > new file mode 100644 > index 0000000..3835761 > --- /dev/null > +++ b/kernel/utrace-gdb.c > @@ -0,0 +1,1148 @@ > +/* > + * utrace-based gdb remote protocol server for user processes > + * > + * Copyright (C) 2009 Red Hat, Inc. All rights reserved. > + * > + * This copyrighted material is made available to anyone wishing to use, > + * modify, copy, or redistribute it subject to the terms and conditions > + * of the GNU General Public License v.2. > + * > + * Red Hat Author: Frank Ch. Eigler > + */ > + > +/* #define DEBUG 1 */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > + > + > +/** struct gdb_connection - Tracks one active gdb-process session. > + */ > + > +#define GDB_BUFMAX 4096 > + > + > +struct gdb_connection { > + pid_t target; > + struct utrace_engine *engine; > + > + /* changed under output_mutex */ > + int at_quiesce_do; > + unsigned char stopcode[GDB_BUFMAX]; // set <=> at_quiesce_do = UTRACE_STOP > + int skip_signals; > + int stop_signals; > + /* XXX: per-thread later */ > + > + char output_buf[GDB_BUFMAX]; > + size_t output_buf_size; > + loff_t output_buf_read; > + struct mutex output_mutex; > + wait_queue_head_t output_wait; > + > + char input_buf[GDB_BUFMAX]; > + size_t input_buf_size; > + struct mutex input_mutex; > + wait_queue_head_t input_wait; > + > + struct list_head link; > +}; > + > + > +static LIST_HEAD(gdb_connections); > +static DEFINE_MUTEX(gdb_connections_mutex); > +static const struct utrace_engine_ops gdb_utrace_ops; > + > + > + > +/* ------------------------------------------------------------------------ */ > + > +static unsigned byteme (unsigned char hex1, unsigned char hex2) > +{ > + return (isdigit(hex1) ? hex1-'0' : tolower(hex1)-'a'+10) * 16 + > + (isdigit(hex2) ? hex2-'0' : tolower(hex2)-'a'+10); > +} > + > + > + > +/* Begin a new packet. Add the $, and remember where we put it. > + * Return the offset for later checksum addition via > + * push_output_packet_end. */ > +static size_t push_output_packet_start (struct gdb_connection *p) > +{ > + size_t start = p->output_buf_size; > + > + BUG_ON (p->output_buf_size + 1 >= GDB_BUFMAX); > + p->output_buf[p->output_buf_size++] = '$'; > + return start; > +} > + > + > +/* Add a character to the output queue. Assumes output_mutex held. */ > +static void push_output (struct gdb_connection *p, unsigned char c) > +{ > + /* We know some space must exist; we check for this in > + proc_gdb_write() for example. */ > + BUG_ON (p->output_buf_size >= GDB_BUFMAX); > + p->output_buf[p->output_buf_size++] = c; > +} > + > + > +static char hex[] = "0123456789ABCDEF"; > + > +/* Add a byte (hexified) to the output queue. Assumes output_mutex held. */ > +static void push_output_hex (struct gdb_connection *p, unsigned char c) > +{ > + /* We know some space must exist; we check for this in > + proc_gdb_write() for example. */ > + BUG_ON (p->output_buf_size >= GDB_BUFMAX); > + p->output_buf[p->output_buf_size++] = hex[(c & 0xf0) >> 4]; > + p->output_buf[p->output_buf_size++] = hex[(c & 0x0f) >> 0]; > +} > + > + > +/* Finish the last packet. Starting after the given '$' offset, compute > + * the checksum and append it. */ > +static void push_output_packet_end (struct gdb_connection *p, size_t start) > +{ > + unsigned char checksum = 0; > + int i; > + > + BUG_ON (p->output_buf_size + 3 >= GDB_BUFMAX); > + BUG_ON (p->output_buf[start] != '$'); > + > + for (i=start+1; ioutput_buf_size; i++) > + checksum += p->output_buf[i]; > + > + p->output_buf[p->output_buf_size++] = '#'; > + p->output_buf[p->output_buf_size++] = hex[(checksum & 0xf0) >> 4]; > + p->output_buf[p->output_buf_size++] = hex[(checksum & 0x0f) >> 0]; > +} > + > + > +/* Add a complete packet payload to the output queue. */ > +static void push_output_packet (struct gdb_connection *p, const char *s) > +{ > + size_t ss = strlen(s); > + size_t start; > + int i; > + > + start = push_output_packet_start(p); > + for (i=0; i + push_output(p, s[i]); > + push_output_packet_end(p, start); > +} > + > + > + > +/* ------------------------------------------------------------------------ */ > + > +/* utrace callbacks */ > + > + > +u32 gdb_utrace_report_quiesce(enum utrace_resume_action action, > + struct utrace_engine *engine, > + struct task_struct *task, > + unsigned long event) > +{ > + struct gdb_connection *p = engine->data; > + pr_debug ("report_quiesce %d event 0x%lx 0x%x->0x%x\n", task->pid, > + event, action, p->at_quiesce_do); > + > + return p->at_quiesce_do; > +} > + > + > +u32 gdb_utrace_report_clone(enum utrace_resume_action action, > + struct utrace_engine *engine, > + struct task_struct *parent, > + unsigned long clone_flags, > + struct task_struct *child) > +{ > + pr_debug ("report_clone %d->%d\n", parent->pid, child->pid); > + > + if (clone_flags & CLONE_THREAD) { > + printk (KERN_WARNING "unsupported multithreading on /proc/%d/gdb.\n", > + task_pid_nr (parent)); > + } > + /* XXX: is there anything else to do here? */ > + return UTRACE_RESUME; > +} > + > + > +u32 gdb_utrace_report_exec(enum utrace_resume_action action, > + struct utrace_engine *engine, > + struct task_struct *task, > + const struct linux_binfmt *fmt, > + const struct linux_binprm *bprm, > + struct pt_regs *regs) > +{ > + /* XXX: Model an exec as if it were an exit. */ > + struct gdb_connection *p = engine->data; > + > + pr_debug ("report_exec %d->%s\n", task->pid, task->comm); > + > + mutex_lock(&p->output_mutex); > + > + p->at_quiesce_do = UTRACE_STOP; > + snprintf (p->stopcode, GDB_BUFMAX, "W%02x", 0); > + push_output_packet (p, p->stopcode); > + > + mutex_unlock(&p->output_mutex); > + wake_up(&p->output_wait); > + > + /* Suspend the exec operation, to ensure that the connected gdb > + receives the notification packet, and lets us go. */ > + return UTRACE_STOP; > +} > + > + > +u32 gdb_utrace_report_signal(u32 action, > + struct utrace_engine *engine, > + struct task_struct *task, > + struct pt_regs *regs, > + siginfo_t *info, > + const struct k_sigaction *orig_ka, > + struct k_sigaction *return_ka) > +{ > + struct gdb_connection *p = engine->data; > + u32 ret = action; > + int kern_p; > + > + mutex_lock(&p->output_mutex); > + > + kern_p = (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))); > + > + pr_debug ("report_signal %d (0x%x) kern %d skip %d stop %d\n", > + task->pid, action, kern_p, p->skip_signals, p->stop_signals); > + > + /* The target is about to receive a signal. There are several > + * cases: > + * > + * 1) This is an ordinary signal. We UTRACE_STOP to notify gdb. > + * > + * 2) This is a SIGTRAP arising from a breakpoint. We UTRACE_STOP. > + * > + * 3) This is a signal our code injected to stop the process, in lieu > + * of UTRACE_INTERRUPT. We UTRACE_STOP | UTRACE_SIGNAL_IGN. > + * > + * 4) This is a signal our code injected on behalf of gdb (C/S/I packets). > + * We UTRACE_RESUME. > + * > + * 5) This is a UTRACE_SIGNAL_REPORT or UTRACE_SIGNAL_HANDLER event. > + * Just let utrace continue, as these signal events of minor internal > + * interest. > + */ > + > + if (utrace_signal_action(action) == UTRACE_SIGNAL_REPORT || > + utrace_signal_action(action) == UTRACE_SIGNAL_HANDLER) { /* case 5 */ > + /* NB: disregard p->at_quiesce_do */ > + ret = UTRACE_RESUME | utrace_signal_action(action); > + } else if (p->skip_signals > 0 /*&& kern_p*/) { /* case 4 */ > + p->skip_signals --; > + p->at_quiesce_do = UTRACE_RESUME; > + ret = UTRACE_RESUME; /* deliver */ > + } else if (p->stop_signals > 0 /*&& kern_p*/) { /* Case 3 */ > + p->stop_signals --; > + snprintf (p->stopcode, GDB_BUFMAX, "S%02x", info->si_signo); > + push_output_packet (p, p->stopcode); > + p->at_quiesce_do = UTRACE_STOP; > + ret = UTRACE_STOP | UTRACE_SIGNAL_IGN; > + } else { /* Cases 1, 2 */ > + snprintf (p->stopcode, GDB_BUFMAX, "S%02x", info->si_signo); > + push_output_packet (p, p->stopcode); > + p->at_quiesce_do = UTRACE_STOP; > + ret = UTRACE_STOP; > + } > + > + pr_debug ("action 0x%x\n", ret); > + > + mutex_unlock(&p->output_mutex); > + wake_up(&p->output_wait); > + > + return ret; > +} > + > + > +u32 gdb_utrace_report_exit(enum utrace_resume_action action, > + struct utrace_engine *engine, > + struct task_struct *task, > + long orig_code, long *code) > +{ > + struct gdb_connection *p = engine->data; > + > + pr_debug ("report_exit %d (%lx)\n", task->pid, (unsigned long) orig_code); > + > + mutex_lock(&p->output_mutex); > + > + p->at_quiesce_do = UTRACE_STOP; > + snprintf (p->stopcode, GDB_BUFMAX, > + "W%02x", (unsigned)(orig_code & 0xFF)); > + push_output_packet (p, p->stopcode); > + > + mutex_unlock(&p->output_mutex); > + wake_up(&p->output_wait); > + > + /* Suspend the exit operation, to ensure that the connected gdb > + receives the notification packet, and lets us go. */ > + return UTRACE_STOP; > +} > + > + > +u32 gdb_utrace_report_death(struct utrace_engine *engine, > + struct task_struct *task, > + bool group_dead, int signal) > +{ > + struct gdb_connection *p = engine->data; > + > + pr_debug ("report_death %d (%d)\n", task->pid, signal); > + > + mutex_lock(&p->output_mutex); > + > + p->at_quiesce_do = UTRACE_DETACH; > + snprintf (p->stopcode, GDB_BUFMAX, "X%2x", (unsigned)(signal & 0xFF)); > + push_output_packet (p, p->stopcode); > + > + p->engine = NULL; > + > + mutex_unlock(&p->output_mutex); > + wake_up(&p->output_wait); > + > + return UTRACE_DETACH; > +} > + > + > + > +static const struct utrace_engine_ops gdb_utrace_ops = { > + .report_quiesce = gdb_utrace_report_quiesce, > + .report_signal = gdb_utrace_report_signal, > + .report_death = gdb_utrace_report_death, > + .report_exit = gdb_utrace_report_exit, > + .report_exec = gdb_utrace_report_exec, > + .report_clone = gdb_utrace_report_clone, > + /* XXX: syscall trapping is also possible. */ > +}; > + > + > + > +/* XXX: arch-dependent lookup of gdb remote protocol register > + * numbering. The register numbers (user-side) & expected sizes come > + * from gdb's regformats/FOO-linux.dat. The regset (kernel-side) > + * numbers could come from offsetof/sizeof constructs based upon each > + * arch's asm/user*.h. > + */ > + > +struct gdb_map_regset { > + unsigned pos; /* regset offset */ > + unsigned count; /* regset byte count */ > + unsigned rsn; /* regset number */ > + unsigned bytes; /* gdb's view of register width; <= count */ > +}; > + > +struct gdb_map_regset arch_i386_map_regset[] = { > + [0]={ /* eax */ 6*4, 4, NT_PRSTATUS, 4, }, > + [1]={ /* ecx */ 1*4, 4, NT_PRSTATUS, 4, }, > + [2]={ /* edx */ 2*4, 4, NT_PRSTATUS, 4, }, > + [3]={ /* ebx */ 0*4, 4, NT_PRSTATUS, 4, }, > + [4]={ /* esp */ 15*4, 4, NT_PRSTATUS, 4, }, > + [5]={ /* ebp */ 5*4, 4, NT_PRSTATUS, 4, }, > + [6]={ /* esi */ 3*4, 4, NT_PRSTATUS, 4, }, > + [7]={ /* edi */ 4*4, 4, NT_PRSTATUS, 4, }, > + [8]={ /* eip */ 12*4, 4, NT_PRSTATUS, 4, }, > + [9]={ /* eflags */ 14*4, 4, NT_PRSTATUS, 4, }, > + [10]={ /* cs */ 13*4, 4, NT_PRSTATUS, 4, }, > + [11]={ /* ss */ 16*4, 4, NT_PRSTATUS, 4, }, > + [12]={ /* ds */ 7*4, 4, NT_PRSTATUS, 4, }, > + [13]={ /* es */ 8*4, 4, NT_PRSTATUS, 4, }, > + [14]={ /* fs */ 9*4, 4, NT_PRSTATUS, 4, }, > + [15]={ /* gs */ 10*4, 4, NT_PRSTATUS, 4, }, > + [16]={ /* st0 */ 0, 0, NT_PRFPREG, 10, }, > + [17]={ /* st1 */ 0, 0, NT_PRFPREG, 10, }, > + [18]={ /* st2 */ 0, 0, NT_PRFPREG, 10, }, > + [19]={ /* st3 */ 0, 0, NT_PRFPREG, 10, }, > + [20]={ /* st4 */ 0, 0, NT_PRFPREG, 10, }, > + [21]={ /* st5 */ 0, 0, NT_PRFPREG, 10, }, > + [22]={ /* st6 */ 0, 0, NT_PRFPREG, 10, }, > + [23]={ /* st7 */ 0, 0, NT_PRFPREG, 10, }, > + [24]={ /* fctrl */ 0, 0, NT_PRFPREG, 4, }, > + [25]={ /* fstat */ 0, 0, NT_PRFPREG, 4, }, > + [26]={ /* ftag */ 0, 0, NT_PRFPREG, 4, }, > + [27]={ /* fiseg */ 0, 0, NT_PRFPREG, 4, }, > + [28]={ /* fioff */ 0, 0, NT_PRFPREG, 4, }, > + [29]={ /* foseg */ 0, 0, NT_PRFPREG, 4, }, > + [30]={ /* fooff */ 0, 0, NT_PRFPREG, 4, }, > + [31]={ /* fop */ 0, 0, NT_PRFPREG, 4, }, > + [32]={ /* xmm0 */ 0, 0, NT_PRFPREG, 16, }, > + [33]={ /* xmm1 */ 0, 0, NT_PRFPREG, 16, }, > + [34]={ /* xmm2 */ 0, 0, NT_PRFPREG, 16, }, > + [35]={ /* xmm3 */ 0, 0, NT_PRFPREG, 16, }, > + [36]={ /* xmm4 */ 0, 0, NT_PRFPREG, 16, }, > + [37]={ /* xmm5 */ 0, 0, NT_PRFPREG, 16, }, > + [38]={ /* xmm6 */ 0, 0, NT_PRFPREG, 16, }, > + [39]={ /* xmm7 */ 0, 0, NT_PRFPREG, 16, }, > + [40]={ /* mxcsr */ 0, 0, NT_PRFPREG, 4, }, > + [41]={ /* orig_eax*/ 0, 0, NT_PRSTATUS, 4, }, > +}; > + > + > +struct gdb_map_regset arch_x86_64_map_regset[] = { > + [0]={ /* rax */ 10*8, 8, NT_PRSTATUS, 8, }, > + [1]={ /* rbx */ 5*8, 8, NT_PRSTATUS, 8, }, > + [2]={ /* rcx */ 11*8, 8, NT_PRSTATUS, 8, }, > + [3]={ /* rdx */ 12*8, 8, NT_PRSTATUS, 8, }, > + [4]={ /* rsi */ 13*8, 8, NT_PRSTATUS, 8, }, > + [5]={ /* rdi */ 14*8, 8, NT_PRSTATUS, 8, }, > + [6]={ /* rbp */ 4*8, 8, NT_PRSTATUS, 8, }, > + [7]={ /* rsp */ 19*8, 8, NT_PRSTATUS, 8, }, > + [8]={ /* r8 */ 9*8, 8, NT_PRSTATUS, 8, }, > + [9]={ /* r9 */ 8*8, 8, NT_PRSTATUS, 8, }, > + [10]={ /* r10 */ 7*8, 8, NT_PRSTATUS, 8, }, > + [11]={ /* r11 */ 6*8, 8, NT_PRSTATUS, 8, }, > + [12]={ /* r12 */ 3*8, 8, NT_PRSTATUS, 8, }, > + [13]={ /* r13 */ 2*8, 8, NT_PRSTATUS, 8, }, > + [14]={ /* r14 */ 1*8, 8, NT_PRSTATUS, 8, }, > + [15]={ /* r15 */ 0*8, 8, NT_PRSTATUS, 8, }, > + [16]={ /* rip */ 16*8, 8, NT_PRSTATUS, 8, }, > + [17]={ /* flags */ 18*8, 8, NT_PRSTATUS, 4, }, > + [18]={ /* cs */ 17*8, 8, NT_PRSTATUS, 4, }, > + [19]={ /* ss */ 20*8, 8, NT_PRSTATUS, 4, }, > + [20]={ /* ds */ 23*8, 8, NT_PRSTATUS, 4, }, > + [21]={ /* es */ 24*8, 8, NT_PRSTATUS, 4, }, > + [22]={ /* fs */ 25*8, 8, NT_PRSTATUS, 4, }, > + [23]={ /* gs */ 26*8, 8, NT_PRSTATUS, 4, }, > + [24]={ /* st0 */ 0, 0, NT_PRFPREG, 10, }, > + [25]={ /* st1 */ 0, 0, NT_PRFPREG, 10, }, > + [26]={ /* st2 */ 0, 0, NT_PRFPREG, 10, }, > + [27]={ /* st3 */ 0, 0, NT_PRFPREG, 10, }, > + [28]={ /* st4 */ 0, 0, NT_PRFPREG, 10, }, > + [29]={ /* st5 */ 0, 0, NT_PRFPREG, 10, }, > + [30]={ /* st6 */ 0, 0, NT_PRFPREG, 10, }, > + [31]={ /* st7 */ 0, 0, NT_PRFPREG, 10, }, > + [32]={ /* fctrl */ 0, 0, NT_PRFPREG, 4, }, > + [33]={ /* fstat */ 0, 0, NT_PRFPREG, 4, }, > + [34]={ /* ftag */ 0, 0, NT_PRFPREG, 4, }, > + [35]={ /* fiseg */ 0, 0, NT_PRFPREG, 4, }, > + [36]={ /* fioff */ 0, 0, NT_PRFPREG, 4, }, > + [37]={ /* foseg */ 0, 0, NT_PRFPREG, 4, }, > + [38]={ /* fooff */ 0, 0, NT_PRFPREG, 4, }, > + [39]={ /* fop */ 0, 0, NT_PRFPREG, 4, }, > + [40]={ /* xmm0 */ 0, 0, NT_PRFPREG, 16, }, > + [41]={ /* xmm1 */ 0, 0, NT_PRFPREG, 16, }, > + [42]={ /* xmm2 */ 0, 0, NT_PRFPREG, 16, }, > + [43]={ /* xmm3 */ 0, 0, NT_PRFPREG, 16, }, > + [44]={ /* xmm4 */ 0, 0, NT_PRFPREG, 16, }, > + [45]={ /* xmm5 */ 0, 0, NT_PRFPREG, 16, }, > + [46]={ /* xmm6 */ 0, 0, NT_PRFPREG, 16, }, > + [47]={ /* xmm7 */ 0, 0, NT_PRFPREG, 16, }, > + [48]={ /* xmm8 */ 0, 0, NT_PRFPREG, 16, }, > + [49]={ /* xmm9 */ 0, 0, NT_PRFPREG, 16, }, > + [50]={ /* xmm10 */ 0, 0, NT_PRFPREG, 16, }, > + [51]={ /* xmm11 */ 0, 0, NT_PRFPREG, 16, }, > + [52]={ /* xmm12 */ 0, 0, NT_PRFPREG, 16, }, > + [53]={ /* xmm13 */ 0, 0, NT_PRFPREG, 16, }, > + [54]={ /* xmm14 */ 0, 0, NT_PRFPREG, 16, }, > + [55]={ /* xmm15 */ 0, 0, NT_PRFPREG, 16, }, > + [56]={ /* mxcsr */ 0, 0, NT_PRFPREG, 4, }, > + [57]={ /* orig_rax*/ 15*8, 8, NT_PRSTATUS, 8, }, > +}; > + > + > + > +static int gdb_remote_register_info(struct gdb_connection *p, > + struct task_struct *task, > + unsigned number, > + unsigned *pos, unsigned *count, > + unsigned *bytes) > +{ > + const struct user_regset_view *rs = task_user_regset_view(task); > + int rsn = -1; > + > + if(rs == 0) > + return -ENOENT; > + > + /* pr_debug ("gdb_remote_register_info rs=%p rs->n=%u\n", rs, rs->n); */ > + > +#define GMRSIZE (sizeof(struct gdb_map_regset)) > + > + if(rs->e_machine == EM_386) { > + if (number < sizeof(arch_i386_map_regset)/GMRSIZE) { > + *pos = arch_i386_map_regset[number].pos; > + *count = arch_i386_map_regset[number].count; > + *bytes = arch_i386_map_regset[number].bytes; > + rsn = arch_i386_map_regset[number].rsn; > + } > + } else if(rs->e_machine == EM_X86_64) { > + if (number < sizeof(arch_x86_64_map_regset)/GMRSIZE) { > + *pos = arch_x86_64_map_regset[number].pos; > + *count = arch_x86_64_map_regset[number].count; > + *bytes = arch_x86_64_map_regset[number].bytes; > + rsn = arch_x86_64_map_regset[number].rsn; > + } > + } /* else ... rsn stays -1. */ > + > +#undef GMRSIZE > + > + /* Now map to the per-architecture regset index, based on the > + elf core_note_type we found. */ > + if (rsn >= 0) { > + unsigned j; > + for(j=0; jn; j++) { > + if(rs->regsets[j].core_note_type == rsn) > + return j; > + } > + } > + > + /* Invalid machines, register numbers, rsns, or unset rsns all > + * fall through here. > + */ > + return -ENOENT; > +} > + > + > + > +/* Process an entire, checksum-confirmed $command# at the front of > + * p->input_buf[]. The input and output mutexes are being held. > + */ > +static void handle_gdb_command_packet (struct gdb_connection *p, struct task_struct *task) > +{ > + unsigned long arg1, arg2, arg3; > + size_t op_start; > + int rc = 0; > + int i, j; > + > + pr_debug ("gdb packet code %c\n", p->input_buf[1]); > + > + switch (p->input_buf[1]) { > + case '?': > + if (p->at_quiesce_do != UTRACE_STOP) { > + /* shouldn't happen */ > + send_sig(SIGTRAP, task, 1); > +#if 0 > + rc = utrace_control (task, p->engine, UTRACE_INTERRUPT); > + if (rc == -EINPROGRESS) > + rc = utrace_barrier(task, p->engine); > +#endif > + > + /* Note that we don't enqueue a reply packet here, > + but make gdb wait for a response from the > + utrace report_FOO callbacks. */ > + p->skip_signals ++; > + } else { > + push_output_packet (p, p->stopcode); > + } > + break; > + > + case 'i': /* [ADDR[,NNN]] */ > + case 's': /* [ADDR] */ > + /* XXX: if !arch_has_single_step() ... then what? */ > + case 'c': /* [ADDR] */ > + rc = sscanf(& p->input_buf[2], "%lx,%lx", &arg1, &arg2); > + if (rc >= 1) { /* Have a PC? */ > + /* XXX: set it */ > + } > + if (rc >= 2) { /* ,NNN present */ > + /* XXX: disregard it. */ > + } > + /* XXX: args ignored */ > + p->stopcode[0]='\0'; > + p->at_quiesce_do = > + ((p->input_buf[1]=='c' || !arch_has_single_step()) > + ? UTRACE_RESUME : UTRACE_SINGLESTEP); > + if (p->at_quiesce_do == UTRACE_SINGLESTEP) > + p->stop_signals ++; > + utrace_control (task, p->engine, p->at_quiesce_do); > + break; > + case 'C': /* SIG[;ADDR] */ > + case 'S': /* SIG[;ADDR] */ > + /* XXX: if !arch_has_single_step() ... then what? */ > + case 'I': /* SIG[;ADDR[,NNN?]] */ > + rc = sscanf(& p->input_buf[2], "%lx;%lx,%lx", &arg1, &arg2, &arg3); > + if (rc >= 1) { /* SIG present */ > + send_sig ((int)arg1, task, 1); > + } > + if (rc >= 2) { /* ;ADDR present */ > + /* XXX: not done */ > + } > + if (rc >= 3) { /* ,NNN present */ > + /* XXX: disregard it. */ > + } > + p->skip_signals ++; > + p->stopcode[0]='\0'; > + p->at_quiesce_do = > + ((p->input_buf[1]=='C' || !arch_has_single_step()) > + ? UTRACE_RESUME : UTRACE_SINGLESTEP); > + if (p->at_quiesce_do == UTRACE_SINGLESTEP) > + p->stop_signals ++; > + utrace_control (task, p->engine, p->at_quiesce_do); > + /* Response will come at next report_signal. */ > + break; > + case 'D': > + push_output_packet (p, "OK"); > + /* NB: the .release fop callback performs actual utrace detach. */ > + break; > + case 'g': > + op_start = push_output_packet_start(p); > + /* GDB_BUFMAX stands for some random large number, > + * known to be larger than the number of gdb indexed > + * registers. */ > + for (i=0; i + unsigned rs_count; > + unsigned rs_pos; > + unsigned bytes; > + const struct user_regset_view* rsv; > + const struct user_regset* rs; > + unsigned char reg_contents[16]; /* maximum reg. width */ > + > + int rsn = gdb_remote_register_info(p, task, i, > + &rs_pos, &rs_count, > + &bytes); > + > + if (rsn < 0) > + break; > + > + /* If we want to extract register data, make sure > + we're fetching at least that much. */ > + BUG_ON (rs_count > 0 && rs_count < bytes); > + /* Assert reg_contents size is right. */ > + BUG_ON(sizeof(reg_contents) < bytes || > + sizeof(reg_contents) < rs_count); > + > + if (rs_count) { /* real register */ > + rsv = task_user_regset_view(task); > + BUG_ON(rsn >= rsv->n); > + rs = & rsv->regsets[rsn]; > + > + /* Extract the register value into reg_contents[]. */ > + rc = (rs->get) (task, rs, rs_pos, rs_count, > + reg_contents, NULL); > + if (rc) > + break; > + } else { /* dummy value */ > + memset (reg_contents, 0, sizeof(reg_contents)); > + } > + > + /* Hex-dump it. */ > + /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u (", > + i, rsn, rs_pos, rs_count, bytes); */ > + /* XXX: endianness adjust for count != bytes */ > + for(j=0; j + /* pr_debug("%02x", reg_contents[j]);*/ > + push_output_hex(p, reg_contents[j]); > + } > + /* pr_debug(")\n"); */ > + > + } > + push_output_packet_end(p, op_start); > + break; > + case 'G': > + i = 0; > + op_start = 2; /* use as input pointer, past $G in command */ > + while(p->input_buf[op_start] != '#' && > + op_start < p->input_buf_size) { > + unsigned rs_count; > + unsigned rs_pos; > + unsigned bytes; > + const struct user_regset_view* rsv; > + const struct user_regset* rs; > + unsigned char reg_contents[16]; /* maximum reg. width */ > + > + int rsn = gdb_remote_register_info(p, task, i, > + &rs_pos, &rs_count, > + &bytes); > + /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u\n", > + i, rsn, rs_pos, rs_count, bytes); */ > + > + if (rsn < 0) > + break; > + > + /* If we want to extract register data, make sure > + we're fetching at least that much. */ > + BUG_ON(rs_count > 0 && rs_count < bytes); > + /* Assert reg_contents size is right. */ > + BUG_ON(sizeof(reg_contents) < bytes || > + sizeof(reg_contents) < rs_count); > + > + /* Remaining packet too short? */ > + if ((op_start + 2*bytes + 3) < p->input_buf_size) > + break; > + > + /* 0-fill the register copy. XXX initialize > + * it from rs->get() instead? > + */ > + memset (reg_contents, 0, sizeof(reg_contents)); > + > + /* Hex-unconvert all the bytes. */ > + /* XXX: endianness adjust for count != bytes */ > + for(j=0; j + reg_contents[j]=byteme(p->input_buf[op_start+2*j], > + p->input_buf[op_start+2*j+1]); > + op_start += 2*bytes; > + > + if (rs_count) { /* real register */ > + BUG_ON(rs_count > sizeof(reg_contents)); > + rsv = task_user_regset_view(task); > + BUG_ON(rsn >= rsv->n); > + rs = & rsv->regsets[rsn]; > + > + /* Set the register value from reg_contents[]. */ > + rc = (rs->set) (task, rs, rs_pos, rs_count, > + reg_contents, NULL); > + if (rc) > + break; > + } else { /* dummy register */ > + ; > + } > + } > + if (p->input_buf[op_start] == '#' && rc == 0) > + push_output_packet (p, "OK"); > + else > + push_output_packet (p, "E01"); > + break; > + case 'p': /* REG */ > + break; > + case 'P': /* REG=VAL */ > + break; > + case 'm': /* ADDR,LENGTH */ > + rc = sscanf(& p->input_buf[2], "%lx,%lx", &arg1, &arg2); > + if (rc != 2) > + push_output_packet(p, "E01"); > + else { > + size_t o = push_output_packet_start (p); > + while (arg2 > 0) { > + unsigned char value; > + > + /* Simply stop looping if requested > + length was too large. gdb will > + probably retry from this point > + on. */ > + if (p->output_buf_size + 5 > GDB_BUFMAX) > + break; > + > + rc = access_process_vm(task, arg1, &value, 1, 0); > + if (rc != 1) > + break; /* EFAULT */ > + else > + push_output_hex (p, value); > + > + arg1++; > + arg2--; > + } > + push_output_packet_end (p, o); > + } > + break; > + case 'M': /* ADDR,LENGTH:XX */ > + /* `i' will index p->input_buf to consume XX hex bytes. */ > + rc = sscanf(& p->input_buf[2], "%lx,%lx:%n", > + &arg1, &arg2, &i); > + op_start = i + 2; /* Skip the leading $M also. */ > + if (rc < 2) { > + push_output_packet(p, "E01"); > + break; > + } > + while (arg2 > 0) { > + unsigned char value; > + > + /* Check that enough input bytes left for > + * these two hex chars, plus the #XX checksum. > + */ > + if (i+4 >= p->input_buf_size) > + break; > + > + value = byteme(p->input_buf[i], > + p->input_buf[i+1]); > + rc = access_process_vm(task, arg1, &value, 1, 1); > + if (rc != 1) > + break; /* EFAULT */ > + > + i += 2; > + arg1++; > + arg2--; > + } > + if (arg2 != 0) > + push_output_packet(p, "E02"); > + else > + push_output_packet(p, "OK"); > + break; > + default: > + push_output_packet (p, ""); > + } > +} > + > + > + > + > +/* ------------------------------------------------------------------------ */ > + > +/* gdb control callbacks */ > + > +#define get_proc_task(inode) get_pid_task(PROC_I((inode))->pid, PIDTYPE_PID) > + > +static int proc_gdb_open(struct inode *inode, struct file *filp) > +{ > + struct task_struct *task = get_proc_task(inode); > + int ret = -EBUSY; > + struct gdb_connection *p; > + struct list_head *l; > + > + pr_debug ("opened /proc/%d/gdb\n", task->pid); > + > + /* Reject kernel threads. */ > + if (task->flags & PF_KTHREAD) { > + ret = -EINVAL; > + goto out; > + } > + > + /* Reject if connection is for other than tg-leader thread. */ > + if (task_pid_nr(task) != task_tgid_nr(task)) { > + ret = -EINVAL; > + goto out; > + } > + > + mutex_lock (& gdb_connections_mutex); > + > + /* Reject if a connection exists for the thread group > + * leader. > + */ > + list_for_each(l, &gdb_connections) { > + p = list_entry (l, struct gdb_connection, link); > + if (p->target == task_tgid_nr(task)) { > + ret = -EBUSY; > + goto out_mutex; > + } > + } > + /* (Don't unlock yet, to defeat a race of two concurrent opens.) */ > + > + p = kzalloc(sizeof (struct gdb_connection), GFP_KERNEL); > + if (!p) { > + ret = -ENOMEM; > + goto out_mutex; > + } > + > + /* Send initial ping to gdb. */ > + push_output_packet (p, ""); > + > + mutex_init(& p->output_mutex); > + init_waitqueue_head(& p->output_wait); > + > + mutex_init(& p->input_mutex); > + init_waitqueue_head(& p->input_wait); > + > + p->target = task->tgid; > + > + /* NB: During attach, we don't want to bother the target. > + Soon though a send_sig will interrupt it. */ > + p->at_quiesce_do = UTRACE_RESUME; > + > + p->engine = utrace_attach_task(task, > + UTRACE_ATTACH_CREATE | > + UTRACE_ATTACH_EXCLUSIVE, > + &gdb_utrace_ops, > + p); > + if (IS_ERR(p->engine) || p->engine==NULL) { > + ret = -EINVAL; > + goto out_free; > + } > + > + ret = utrace_set_events(task, p->engine, > + UTRACE_EVENT_SIGNAL_ALL| > + UTRACE_EVENT(QUIESCE)| > + UTRACE_EVENT(DEATH)| > + UTRACE_EVENT(EXIT)| > + UTRACE_EVENT(EXEC)| > + UTRACE_EVENT(CLONE)); > + pr_debug ("utrace_set_events sent, ret=%d\n", ret); > + if (!ret) > + ; > + > + filp->private_data = p; > + > + INIT_LIST_HEAD(& p->link); > + list_add(&gdb_connections, &p->link); > + > + p->stop_signals ++; > + send_sig(SIGTRAP, task, 1); > +#if 0 > + ret = utrace_control(task, p->engine, UTRACE_INTERRUPT); > + if (ret == -EINPROGRESS) > + ret = utrace_barrier(task, p->engine); > +#endif > + > + goto out_mutex; > + > +out_free: > + kfree(p); > +out_mutex: > + mutex_unlock (& gdb_connections_mutex); > +out: > + return ret; > +} > + > + > +static int proc_gdb_release(struct inode *inode, struct file *filp) > +{ > + struct task_struct *task = get_proc_task(inode); > + struct gdb_connection *p = filp->private_data; > + int ret = 0; > + > + mutex_lock (& gdb_connections_mutex); > + > + if (task == NULL) { > + /* The thread is already gone; report_death was already called. */ > + pr_debug ("gdb %d releasing old\n", p->target); > + } else { > + pr_debug ("gdb %d releasing current\n", p->target); > + > + ret = utrace_set_events(task, p->engine, 0); > + if (ret == -EINPROGRESS) > + ret = utrace_barrier(task, p->engine); > + /* No more callbacks will be received! */ > + > + ret = utrace_control(task, p->engine, UTRACE_DETACH); /* => RESUME */ > + if (ret == -EINPROGRESS) > + ret = utrace_barrier(task, p->engine); > + > + utrace_engine_put (p->engine); > + } > + > + list_del(&p->link); > + kfree(p); > + > + mutex_unlock (& gdb_connections_mutex); > + > + return ret; > +} > + > + > + > +static int proc_gdb_ioctl(struct inode *inode, struct file *file, > + unsigned int cmd, unsigned long arg) > +{ > + /* XXX: GDB usually thinks that a file name for "target > + * remote" implies a serial port with tty-ish ioctl's > + * available. We pretend to accept them all. */ > + return 0; > +} > + > + > + > +static ssize_t proc_gdb_read(struct file *filp, char __user *buf, > + size_t count, loff_t *ppos) > +{ > + struct gdb_connection *p = filp->private_data; > + struct task_struct *task; > + int rc = 0; > + size_t len; > + > + task = find_task_by_vpid (p->target); > + if (!task) > + return -EINVAL; > + > + if ((p->output_buf_size <= p->output_buf_read) && > + filp->f_flags & O_NONBLOCK) > + return -EAGAIN; > + > +again: > + rc = wait_event_interruptible (p->output_wait, > + (p->output_buf_size > p->output_buf_read)); > + if (rc) > + goto out; > + > + mutex_lock(&p->output_mutex); > + > + if(p->output_buf_size <= p->output_buf_read) { > + mutex_unlock(&p->output_mutex); > + goto again; > + } > + > + len = min (count, (size_t)(p->output_buf_size - p->output_buf_read)); > + if (copy_to_user (buf, & p->output_buf[p->output_buf_read], len)) { > + rc = -EFAULT; > + goto out_unlock; > + } > + > + pr_debug ("sent %u bytes (%ld left) data (%.*s)\n", > + (unsigned)len, > + ((long)p->output_buf_size-(long)p->output_buf_read)-len, > + (int)len, & p->output_buf[p->output_buf_read]); > + > + p->output_buf_read += len; > + rc = len; > + > + /* If whole packet is consumed, reset for next one. */ > + BUG_ON (p->output_buf_read > p->output_buf_size); > + if (p->output_buf_read == p->output_buf_size) { > + p->output_buf_read = 0; > + p->output_buf_size = 0; > + } > + > +out_unlock: > + mutex_unlock(&p->output_mutex); > + > +out: > + return rc; > +} > + > + > +static ssize_t proc_gdb_write(struct file *filp, const char __user *buf, > + size_t count, loff_t *ppos) > +{ > + struct gdb_connection *p = filp->private_data; > + size_t last_input_buf_size; > + struct task_struct *task; > + size_t len; > + int ret = 0; > + > + task = find_task_by_vpid (p->target); > + if (!task) > + return -EINVAL; > + > +again: > + ret = wait_event_interruptible (p->input_wait, > + (p->input_buf_size < GDB_BUFMAX)); > + if (ret) > + goto out; > + > + mutex_lock(&p->input_mutex); > + if (p->input_buf_size == GDB_BUFMAX) { > + mutex_unlock(&p->input_mutex); > + goto again; > + } > + mutex_lock(&p->output_mutex); > + > + /* We now know there is some room in the input buffer. Upon > + entry, the input_buf will either be empty, or contain a > + partial gdb request packet. */ > + > + /* Copy the data. */ > + len = min (count, (size_t)(GDB_BUFMAX - p->input_buf_size)); > + if (copy_from_user (& p->input_buf[p->input_buf_size], buf, len)) { > + ret = -EFAULT; > + goto out_unlock; > + } > + > + /* pr_debug ("received data %.*s\n", (int)len, & p->input_buf[p->input_buf_size]); */ > + > + p->input_buf_size += len; > + ret = len; > + > + /* Process any packets in the buffer to restore the incoming > + invariant. (Normal GDB will not send more than one packet > + before waiting for a response.) */ > + > + /* We iterate until we can no longer shrink the input buffer. Usually > + we will not iterate more than once, since there may be one +/- > + ack byte and/or one gdb packet. */ > + last_input_buf_size = 0; > + while (p->input_buf_size > + && p->input_buf_size != last_input_buf_size) { > + last_input_buf_size = p->input_buf_size; > + > + if (p->input_buf[0] == '+') { > + /* This must have been an ack to our > + * previously output packet. > + * Consume the input. > + */ > + memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); > + } else if (p->input_buf[0] == '-') { > + /* Whoops, a nak. Unfortunately, we don't > + * handle transmission errors by > + * retransmitting the last output_buf; it's > + * already gone. OTOH we should not encounter > + * transmission errors on a reliable channel > + * such as a read syscall. > + * Consume the input. > + */ > + printk(KERN_WARNING "Unexpected NAK received" > + "on /proc/%d/gdb connection.\n", task_pid_nr(task)); > + memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); > + } else if (p->input_buf[0] == 3) { /* ^C == INTR */ > + /* NB: don't overwrite 'ret'. */ > + pr_debug ("received gdb interrupt\n"); > + p->stop_signals ++; > + send_sig(SIGTRAP, task, 1); > +#if 0 > + int rc = utrace_control(task, p->engine, UTRACE_INTERRUPT); > + if (rc == -EINPROGRESS) > + rc = utrace_barrier(task, p->engine); > +#endif > + /* p->at_quiesce_do will be set in report_signal(SIGNAL_REPORT) */ > + /* NB: this packet does not generate an +/- ack. > + Consume the input. */ > + memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); > + } else if (p->input_buf[0] == '$') { /* command packet */ > + int j; > + unsigned char checksum = 0; > + for (j=1; jinput_buf_size-2; j++) { > + if (p->input_buf[j] == '#') { > + unsigned char checksum2; > + checksum2 = byteme (p->input_buf[j+1], > + p->input_buf[j+2]); > + pr_debug ("received gdb packet %.*s\n", > + j+3, & p->input_buf[0]); > + if (checksum == checksum2) { > + push_output (p, '+'); > + handle_gdb_command_packet (p, task); > + } else { > + push_output (p, '-'); > + } > + /* Consume the whole packet. */ > + p->input_buf_size -= (j+3); > + memmove(&p->input_buf[0], &p->input_buf[j+3], > + p->input_buf_size); > + break; > + } else { > + checksum += p->input_buf[j]; > + } > + } /* End searching for end of packet */ > + > + /* We may not have found the # > + * checksum. If so, leave the partial packet > + * in input_buf. Since input_buf_size will > + * not have decreased, the while() loop above > + * will detect a fixpoint and exit. > + * > + * Alternately, there could be another gdb packet > + * just behind the one we just consumed. In this > + * we'll iterate one more time in this loop. > + */ > + } else { /* junk character */ > + printk(KERN_WARNING "Unexpected character (%x) received" > + " on /proc/%d/gdb connection.\n", > + (int) p->input_buf[0], task_pid_nr(task)); > + /* Consume the input. */ > + memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); > + } > + } > + > +out_unlock: > + wake_up(&p->input_wait); /* Probably have more room in input_buf. */ > + wake_up(&p->output_wait); /* Probably have data in output_buf. */ > + > + mutex_unlock(&p->output_mutex); > + mutex_unlock(&p->input_mutex); > +out: > + return ret; > +} > + > + > +const struct file_operations proc_gdb_operations = { > + .open = proc_gdb_open, > + .read = proc_gdb_read, > + .write = proc_gdb_write, > + .release = proc_gdb_release, > + .ioctl = proc_gdb_ioctl, > +}; > + > + From yamanetenyuu at thenbs.com Thu Jul 9 22:34:29 2009 From: yamanetenyuu at thenbs.com (Isaac Hunt) Date: Thu, 9 Jul 2009 19:34:29 -0300 Subject: Hold away your finish line Message-ID: <000a01ca00e5$6c02e400$35e2ef29@fabiojplq> No need to spend hours searching chemist's around! http://hu.maslyzraeg.com/ From jaybird at palmsresort.com Fri Jul 10 10:39:02 2009 From: jaybird at palmsresort.com (jaybird) Date: Fri, 10 Jul 2009 11:39:02 +0100 Subject: Passionate sex Forever, Part II - Seccrets You Should Knnow Message-ID: <1A77@palmsresort.com> Passionate sex Froever, Part II - Secrrets You Should Know www. ku17. net. China offers pvolitically coorrect maps online From shachar at shemesh.biz Sat Jul 11 08:07:51 2009 From: shachar at shemesh.biz (Shachar Shemesh) Date: Sat, 11 Jul 2009 11:07:51 +0300 Subject: Where has GETSIGINFO gone? Message-ID: <4A584857.3040709@shemesh.biz> Hi all, I was somewhat surprised to find in LWN a message, posted to this list[1], suggesting that a project of mine, fakeroot-ng, is a potential beneficiary of utrace. Truth be told, all utrace has offered me so far is pain. In particular, when working with ptrace to perform generic virtualization, one runs against an interesting problem. The core ptrace interface is notifying the debugger about events delivered at the debuggee. Whenever "interesting" events are reported (such as single step or a system call), this appears to the debugger to be a SIGTRAP delivered at the debugee process. Particularly for system calls tracing, the debugger needs to keep track over how many times it was notified, as it will get two notifications for each system call - one upon entry and one upon exit. I'm fairly sure that I'm not saying anything which is news to almost everyone on this list. The problem is that, as a debugger, I need to be able to differentiate between a SIGTRAP supposedly delivered to the debuggee because I asked to trace the system calls, and a SIGTRAP actually delivered to the debuggee. If I don't, my count is going to be off, and I will totally mis-interpret the debugee's state. The best way, as far as I can tell, to do that on Linux is to use the PTRACE_GETSIGINFO command. This provides me with a field, si_code, that can distinguish between a signal and a system call. This is important to make sure that I don't get confused over which is which. Unfortunately, utrace (at least the version integrated into the Fedora Core 9 and Fedore 10 kernels) totally eliminated this system call. When calling ptrace with PTRACE_GETSIGINFO I get back "Invalid argument". I've tried to figure out how other programs handle the situation. Looking at the strace sources, it seems to use a heuristics in order to try and detect this state. It relies on the fact that, on most Linux platforms, the kernel sets the return code register to -ENOSYS before calling the syscall enter ptrace hook, and tries to detect spurious SIGTRACE if the value is not set. This solution has numerous deficiencies: * It is platform specific. On PowerPC, for example, the kernel does not, and strace has no way of telling the two cases apart. * It is non-reliable. The check can only be made on the syscall enter hook, not the exit hook. * It relies on internal kernel behavior * It is easy to fool by a malicious programmer. For example, send the signal from another process, have the first process do a tight loop where EAX (or whatever) is set to -ENOSYS, and strace will think you have entered a random system call, probably the last one again. Do that right after a fork or an exec, and all sorts of fun stuff will happen. Since I'm aiming to use the fakeroot-ng technology for security related stuff (not in fakeroot-ng - I intend to split the project), these drawbacks are fatal. Don't get me wrong. I think cleaning up the debugger interfaces inside the kernel is an excellent idea. I just don't think breaking user space compatibility over the old interface, broken though you might think it is, is justified. This is directed not so much against the utrace project as it is against RedHat including it in production kernels. Shachar [1] - http://www.redhat.com/archives/utrace-devel/2009-March/msg00112.html -- Shachar Shemesh Lingnu Open Source Consulting Ltd. http://www.lingnu.comhttp://www.redhat.com/archives/utrace-devel/2009-March/msg00112.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From kathleen.keenan at lgs.de Sat Jul 11 15:29:46 2009 From: kathleen.keenan at lgs.de (Neddy Gregory) Date: Sat, 11 Jul 2009 12:29:46 -0300 Subject: Take her hole easily Message-ID: <001201ca023c$6c2d4580$486f504f@ADMINISTRADORswkrhn> Get it up fast and simply http://eo.gxumuciw.cn/ From fche at redhat.com Sun Jul 12 02:11:09 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Sat, 11 Jul 2009 22:11:09 -0400 Subject: Where has GETSIGINFO gone? In-Reply-To: <4A584857.3040709@shemesh.biz> (Shachar Shemesh's message of "Sat, 11 Jul 2009 11:07:51 +0300") References: <4A584857.3040709@shemesh.biz> Message-ID: Shachar Shemesh writes: > [...] The best way, as far as I can tell, to do that on Linux is to > use the PTRACE_GETSIGINFO command. [...] Unfortunately, utrace (at > least the version integrated into the Fedora Core 9 and Fedore 10 > kernels) totally eliminated this system call. When calling ptrace > with PTRACE_GETSIGINFO I get back "Invalid argument". [...] I just > don't think breaking user space compatibility over the old > interface, broken though you might think it is, is justified. The version of utrace I see lying around does not flat out disable GETSIGINFO, but does return -EINVAL under some circumstances. I believe that any incompatibility with classical ptrace is unintended. Would you be willing to submit a bugzilla.redhat.com report, with a reproducing example, please? > This is directed not so much against the utrace project as it is > against RedHat including it in production kernels. The costs so far have been far outweighed by the benefits, FWIW. - FChE From shachar at shemesh.biz Sun Jul 12 05:42:01 2009 From: shachar at shemesh.biz (Shachar Shemesh) Date: Sun, 12 Jul 2009 08:42:01 +0300 Subject: Where has GETSIGINFO gone? In-Reply-To: References: <4A584857.3040709@shemesh.biz> Message-ID: <4A5977A9.8070109@shemesh.biz> Frank Ch. Eigler wrote: > Shachar Shemesh writes: > > >> [...] The best way, as far as I can tell, to do that on Linux is to >> use the PTRACE_GETSIGINFO command. [...] Unfortunately, utrace (at >> least the version integrated into the Fedora Core 9 and Fedore 10 >> kernels) totally eliminated this system call. When calling ptrace >> with PTRACE_GETSIGINFO I get back "Invalid argument". [...] I just >> don't think breaking user space compatibility over the old >> interface, broken though you might think it is, is justified. >> > > The version of utrace I see lying around does not flat out disable > GETSIGINFO, but does return -EINVAL under some circumstances. Version 0.16 of fakeroot-ng had a quite major changes so that it would not rely on the FORK/VFORK detection for attaching to new processes, as that would simply not work on Fedora Core 9. If you want something that works on vanilla kernels but not on utrace, look no further than fakeroot-ng version 0.15. I'm not particularly sorry about this change, as it makes things less platform specific, and thus easier to port to non-Linux platforms. This does not make me like utrace much more, however... :-( > I > believe that any incompatibility with classical ptrace is unintended. > Would you be willing to submit a bugzilla.redhat.com report, with a > reproducing example, please? > The example I have right now (differentiating SIGTRAP from ptrace events) I get to by modifying the fakeroot-ng source. This is quite a far cry from a reduced small and compact test case, I admit. I will try to construct a more compact example and post it to bugzilla. No promises. > >> This is directed not so much against the utrace project as it is >> against RedHat including it in production kernels. >> > > The costs so far have been far outweighed by the benefits, FWIW. > I know this has been discussed before, but I, personally, have not been able to understand what those benefits are. With no new user space APIs, utrace only affects the kernel internals. If you are doing a lot of kernel development or complicated debugging scenarios, then, sure, I can see how utrace can be of help. For production kernels, however, I should have expected that things would be more stable than that. Renzo seems to think I should write a "fakeroot-ng kernel module". While an interesting concept, I'm afraid that this will either totally violate my design or will not gain me anything. Fakeroot-ng was built the way it was built, to a large degree, to make it easier to port to new platforms, and putting code that is even more platform dependent than it is now goes against the design decisions, as far as I'm concerned. Had userspace APIs already existed, then I might conceivably use them, but asking the user to load a module just so they can emulate a root environment from user space is, well, self contradicting. The whole point of fakeroot-ng is that you do NOT need to be root in order to run it. I'm not saying ptrace does not have deficiencies. It is a terrible interface to do useful things with. All I'm saying is that, as long as utrace is kernel only, comparing the two is comparing apples to oranges. They are sort of the same, only extremely different. I need to stress again. This rant is not against the utrace project, as it sounds like an interesting and needed cleanup. This is against RedHat including this (obviously not complete) change into their production kernels. > - FChE > Shachar -- Shachar Shemesh Lingnu Open Source Consulting Ltd. http://www.lingnu.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From shachar at shemesh.biz Sun Jul 12 07:09:48 2009 From: shachar at shemesh.biz (Shachar Shemesh) Date: Sun, 12 Jul 2009 10:09:48 +0300 Subject: Where has GETSIGINFO gone? In-Reply-To: References: <4A584857.3040709@shemesh.biz> Message-ID: <4A598C3C.9000809@shemesh.biz> Frank Ch. Eigler wrote: > Shachar Shemesh writes: > > >> [...] The best way, as far as I can tell, to do that on Linux is to >> use the PTRACE_GETSIGINFO command. [...] Unfortunately, utrace (at >> least the version integrated into the Fedora Core 9 and Fedore 10 >> kernels) totally eliminated this system call. When calling ptrace >> with PTRACE_GETSIGINFO I get back "Invalid argument". [...] I just >> don't think breaking user space compatibility over the old >> interface, broken though you might think it is, is justified. >> > > The version of utrace I see lying around does not flat out disable > GETSIGINFO, but does return -EINVAL under some circumstances. I > believe that any incompatibility with classical ptrace is unintended. > Would you be willing to submit a bugzilla.redhat.com report, with a > reproducing example, please? > https://bugzilla.redhat.com/show_bug.cgi?id=510894 > >> This is directed not so much against the utrace project as it is >> against RedHat including it in production kernels. >> > > The costs so far have been far outweighed by the benefits, FWIW. > > - FChE > -- Shachar Shemesh Lingnu Open Source Consulting Ltd. http://www.lingnu.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From drfa42 at msn.com Sun Jul 12 17:14:44 2009 From: drfa42 at msn.com (Dr. Frank Awosu) Date: Sun, 12 Jul 2009 13:14:44 -0400 Subject: Very Important Information, Get Back To Me As Soon As Possible !!! Message-ID: <200907121714.n6CHEiY2023199@holsteinworld.com> Dear Friend, I have a discrete and mutual profitable business proposal for you. I plead that you not to distribute this information if you are not interested, for my safety. I worked for the Late Wright Lan Roger who just died in his private-jet along with his entire family in the recent plane crash in the month of May 2009. I need your assistance to move out some funds belonging to him that was deposited with well reputable company here in my country. I have decided to offer you 40% of these funds for your assistance. The total fund is $35.8Million US Dollars. For your confirmation, you can view the below link to prove his death: http://news.sky.com/skynews/Home/World-News/Brazil-Businessman-Roger-Wright-And-Family-Die-In-Plane-Crash-In-Trancoso/Article/200905415287531 http://www.zimbio.com/Aviation/articles/440/Updated+Airplane+crash+brings+heavy+death I am in contact with the storage company where the funds were lodged. I also have all the documents for the collection of this deposit and will provide you more detail as soon as you reply. Please this is urgent and I need your utmost attention. Thanks, Yours sincerely, Dr. Frank Awosu. From fireless at ghs.l.google.com Sun Jul 12 23:10:13 2009 From: fireless at ghs.l.google.com (Vanwormer) Date: Sun, 12 Jul 2009 22:10:13 -0100 Subject: famishment Message-ID: <0c0e398d71e9229b3622_AjKv@than.org> Sbex Inn Old Age.www_se57_net From barycentre at powerware.it Mon Jul 13 15:14:37 2009 From: barycentre at powerware.it (Cutchember) Date: Mon, 13 Jul 2009 14:14:37 -0100 Subject: lues Message-ID: <1247494319.spotless@powerware.it> Multi-aTlented Lingerie Modeels.www+za16+com From drow at false.org Mon Jul 13 15:55:21 2009 From: drow at false.org (Daniel Jacobowitz) Date: Mon, 13 Jul 2009 11:55:21 -0400 Subject: Where has GETSIGINFO gone? In-Reply-To: <4A584857.3040709@shemesh.biz> References: <4A584857.3040709@shemesh.biz> Message-ID: <20090713155521.GA16733@caradoc.them.org> On Sat, Jul 11, 2009 at 11:07:51AM +0300, Shachar Shemesh wrote: > The problem is that, as a debugger, I need to be able to > differentiate between a SIGTRAP supposedly delivered to the debuggee > because I asked to trace the system calls, and a SIGTRAP actually > delivered to the debuggee. If I don't, my count is going to be off, > and I will totally mis-interpret the debugee's state. > > The best way, as far as I can tell, to do that on Linux is to use the > PTRACE_GETSIGINFO command. This provides me with a field, si_code, > that can distinguish between a signal and a system call. This is > important to make sure that I don't get confused over which is which. Have you seen PTRACE_SETOPTIONS and PTRACE_O_TRACESYSGOOD? -- Daniel Jacobowitz CodeSourcery From cornel at upload-ro.ro Mon Jul 13 15:18:38 2009 From: cornel at upload-ro.ro (cornel) Date: Mon, 13 Jul 2009 18:18:38 +0300 Subject: Untitled-1 Message-ID: <20090713.YFQLUOJVCBFYKLJM@upload-ro.ro> An HTML attachment was scrubbed... URL: From srikar at linux.vnet.ibm.com Mon Jul 13 17:22:37 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Mon, 13 Jul 2009 22:52:37 +0530 Subject: linux kernel gdb stub for userspace processes, prototype version 3 In-Reply-To: <20090707042639.GC25935@redhat.com> References: <20090707042639.GC25935@redhat.com> Message-ID: <20090713172237.GC23645@linux.vnet.ibm.com> Hi Frank, Roland Using UTRACE_STOP as action in report_signal and report_quiesce results in utrace_stop() being called which causes the thread to be scheduled out. This results in gdb not getting control/data from the remote and results in gdb command prompt. >From looking at kgdb-stub, I feel it might be better for report_signal() to wait on gdb stub for inputs from gdb client. This is similar to what kgdb stub does currently. Also when gdb wants control, (i.e pressing ^C in gdb to get gdb prompt) stub seems to inject SIGTRAP, I think gdb stub should have used utrace_control(UTRACE_STOP) instead of sending SIGTRAP. Please let me know if I am missing something. -- Thanks and Regards Srikar PS: I am attaching the gdb screen and dmesg output. Please note the sections under NOTE Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu"... (gdb) target remote /proc/4870/gdb Remote debugging using /proc/4870/gdb Reading symbols from /lib64/libtermcap.so.2...done. Loaded symbols for /lib64/libtermcap.so.2 Reading symbols from /lib64/libdl.so.2...Reading symbols from /usr/lib/debug/lib64/libdl-2.5.so.debug...done. done. Loaded symbols for /lib64/libdl.so.2 Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/lib64/libc-2.5.so.debug...done. done. Loaded symbols for /lib64/libc.so.6 Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib64/ld-2.5.so.debug...done. done. Loaded symbols for /lib64/ld-linux-x86-64.so.2 Reading symbols from /lib64/libnss_files.so.2...Reading symbols from /usr/lib/debug/lib64/libnss_files-2.5.so.debug...done. done. Loaded symbols for /lib64/libnss_files.so.2 0x0000003b4aec5620 in __read_nocancel () from /lib64/libc.so.6 (gdb) csource .gdbinit_bash (gdb) c Continuing. Sending packet: $Z0,3b4aa0d9f0,1#01...Ack Packet received: Packet Z0 (software-breakpoint) is NOT supported Sending packet: $m3b4aa0d9f0,1#b8...Ack Packet received: F3 Sending packet: $X3b4aa0d9f0,0:#dc...Ack Packet received: binary downloading NOT suppported by target Sending packet: $M3b4aa0d9f0,1:cc#98...Ack Packet received: OK Sending packet: $vCont?#49...Ack Packet received: Packet vCont (verbose-resume) is NOT supported Sending packet: $Hc0#db...Ack Packet received: Sending packet: $c#63...Ack Packet received: S11 Sending packet: $g#67...Ack Packet received: 00000000000000000000000000000000FFFFFFFFFFFFFFFF40558F6DFF7F000070568F6DFF7F00001100000000000000000000000000000038558F6DFF7F0000C0B4A40000000000000000000000000008000000000000004602000000000000000000000000000000000000000000000100000000000000D0B3A30000000000806043000000000046020000330000002B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E00000000000000 Program received signal SIGSTOP, Stopped (signal). ########################################################################### NOTE: Here gdb client was actually trying to get more data from server stub. However utrace_stop() was called from server stub, resulting in the thread being scheduled out. Ideally stub has sent a S packet to gdb client. Stub should wait for comments from gdb client and report accordingly. When the client finally says detach, continue or single step, then report_signal() should sent the response accordingly. (which would be UTRACE_RESUME/_SINGLESTEP but probably not UTRACE_STOP ########################################################################## Sending packet: $M3b4aa0d9f0,1:f3#6b...Ack Packet received: OK sigchld_handler (sig=17) at jobs.c:2937 2937 { (gdb) c Continuing. ########################################################################## NOTE: Here again client is not sending us continue or step/detach packets to stub/server. This is because client is in STOPPED state and not ready to accept packets. Hence it directly asks the process to be continued.. which shouldnt be the case in a remote debugging. ########################################################################## Sending packet: $m3b4aa0d9f0,1#b8...Ack Packet received: F3 Sending packet: $M3b4aa0d9f0,1:cc#98...Ack Packet received: OK Sending packet: $C11#a5...Ack Packet received: W00 Program exited normally. (gdb) q kecho\]0;srikar at llm37.in.ibm.com:\997 [srikar at llm37 ~]$ exit Script done on Fri 10 Jul 2009 06:04:22 PM IST stap_becadeb76113dc76006d007e1c50b687_66017: systemtap: 0.9.8/0.141, base: ffffffffa0d8b000, memory: 1828873+93351+58816+14000 data+text+ctx+net, probes: 114 opened /proc/4870/gdb utrace_set_events sent, ret=0 report_signal 4870 (0x65) kern 1 skip 0 stop 1 action 0x65 received gdb packet $qSupported#37 gdb packet code q sent 9 bytes (0 left) data ($#00+$#00) report_signal 4870 (0x5) kern 1 skip 0 stop 1 action 0x10 received gdb packet $?#3f gdb packet code ? sent 15 bytes (0 left) data ($S05#B8+$S05#B8) received gdb packet $Hc-1#09 gdb packet code H sent 5 bytes (0 left) data (+$#00) received gdb packet $qC#b4 gdb packet code q sent 5 bytes (0 left) data (+$#00) received gdb packet $qOffsets#4b gdb packet code q sent 5 bytes (0 left) data (+$#00) received gdb packet $Hg0#df gdb packet code H sent 5 bytes (0 left) data (+$#00) received gdb packet $g#67 gdb packet code g sent 1093 bytes (0 left) data (+$00FEFFFFFFFFFFFFA006154B3B000000FFFFFFFFFFFFFFFF0100000000000000D7498F6DFF7F00000000000000000000D7498F6DFF7F0000B8498F6DFF7F000000000000000000000100000000000000080000000000000046020000000000000000000000000000084B8F6DFF7F000070598F6DFF7F000000000000000000002056EC4A3B00000046020000330000002B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000<7>received gdb packet $m6b20d0,8#5f gdb packet code m sent 21 bytes (0 left) data (+$60CCC14A3B000000#6A) received gdb packet $m3b4ac1cc68,8#c3 gdb packet code m sent 21 bytes (0 left) data (+$0080D389707F0000#54) received gdb packet $m7f7089d38000,28#d7 gdb packet code m sent 85 bytes (0 left) data (+$00000000000000001F81A14A3B00000028206B00000000008885D389707F00000000000000000000#E9) received gdb packet $m7f7089d38588,28#ec gdb packet code m sent 85 bytes (0 left) data (+$00E0226EFF7F00001F81A14A3B000000E0E3926DFF7F00005876D389707F00000080D389707F0000#2E) received gdb packet $m3b4aa1811c,4#86 gdb packet code m sent 13 bytes (0 left) data (+$20090A00#9C) received gdb packet $m7f7089d37658,28#e9 gdb packet code m sent 85 bytes (0 left) data (+$00000000000000004076D389707F0000B02A004D3B000000187BD389707F00008885D389707F0000#86) received gdb packet $m7f7089d37640,4#aa gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m7f7089d37644,4#ae gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m7f7089d37648,4#b2 gdb packet code m sent 13 bytes (0 left) data (+$69627465#AD) received gdb packet $m7f7089d3764c,4#dd gdb packet code m sent 13 bytes (0 left) data (+$726D6361#B3) received gdb packet $m7f7089d37650,4#ab gdb packet code m sent 13 bytes (0 left) data (+$702E736F#C4) received gdb packet $m7f7089d37654,4#af gdb packet code m sent 13 bytes (0 left) data (+$2E320000#9C) received gdb packet $m7f7089d37b18,28#11 gdb packet code m sent 85 bytes (0 left) data (+$0000000000000000007BD389707F0000A02D804B3B0000000040D289707F00005876D389707F0000#74) received gdb packet $m7f7089d37b00,4#d2 gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m7f7089d37b04,4#d6 gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m7f7089d37b08,4#da gdb packet code m sent 13 bytes (0 left) data (+$6962646C#BA) received gdb packet $m7f7089d37b0c,4#05 gdb packet code m sent 13 bytes (0 left) data (+$2E736F2E#D4) received gdb packet $m7f7089d37b10,4#d3 gdb packet code m sent 13 bytes (0 left) data (+$32000000#85) received gdb packet $m7f7089d24000,28#d2 gdb packet code m sent 85 bytes (0 left) data (+$0000000000000000C07FD389707F000060FB144B3B000000E8C4C14A3B000000187BD389707F0000#BA) received gdb packet $m7f7089d37fc0,4#09 gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m7f7089d37fc4,4#0d gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m7f7089d37fc8,4#11 gdb packet code m sent 13 bytes (0 left) data (+$6962632E#B7) received gdb packet $m7f7089d37fcc,4#3c gdb packet code m sent 13 bytes (0 left) data (+$736F2E36#C6) received gdb packet $m7f7089d37fd0,4#0a gdb packet code m sent 13 bytes (0 left) data (+$00000000#80) received gdb packet $m3b4ac1c4e8,28#f5 gdb packet code m sent 85 bytes (0 left) data (+$0000000000000000380240000000000008BEC14A3B000000D0628C00000000000040D289707F0000#04) received gdb packet $m400238,4#fe gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m40023c,4#29 gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m400240,4#f7 gdb packet code m sent 13 bytes (0 left) data (+$642D6C69#C8) received gdb packet $m400244,4#fb gdb packet code m sent 13 bytes (0 left) data (+$6E75782D#CC) received gdb packet $m400248,4#ff gdb packet code m sent 13 bytes (0 left) data (+$7838362D#B9) received gdb packet $m40024c,4#2a gdb packet code m sent 13 bytes (0 left) data (+$36342E73#B1) received gdb packet $m400250,4#f8 gdb packet code m sent 13 bytes (0 left) data (+$6F2E3200#B8) received gdb packet $m8c62d0,28#9a gdb packet code m sent 85 bytes (0 left) data (+$00905486707F0000D0588C0000000000F82D7586707F00000000000000000000E8C4C14A3B000000#64) received gdb packet $m8c58d0,4#69 gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m8c58d4,4#6d gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m8c58d8,4#71 gdb packet code m sent 13 bytes (0 left) data (+$69626E73#BC) received gdb packet $m8c58dc,4#9c gdb packet code m sent 13 bytes (0 left) data (+$735F6669#C0) received gdb packet $m8c58e0,4#6a gdb packet code m sent 13 bytes (0 left) data (+$6C65732E#C5) received gdb packet $m8c58e4,4#6e gdb packet code m sent 13 bytes (0 left) data (+$736F2E32#C2) received gdb packet $m8c58e8,4#72 gdb packet code m sent 13 bytes (0 left) data (+$00588C00#A8) received gdb packet $m3b4ac1cc60,4#b7 gdb packet code m sent 13 bytes (0 left) data (+$01000000#81) received gdb packet $qSymbol::#5b gdb packet code q sent 5 bytes (0 left) data (+$#00) received gdb packet $m6b20d0,8#5f gdb packet code m sent 21 bytes (0 left) data (+$60CCC14A3B000000#6A) received gdb packet $m3b4ac1cc68,8#c3 gdb packet code m sent 21 bytes (0 left) data (+$0080D389707F0000#54) received gdb packet $m7f7089d38000,28#d7 gdb packet code m sent 85 bytes (0 left) data (+$00000000000000001F81A14A3B00000028206B00000000008885D389707F00000000000000000000#E9) received gdb packet $m7f7089d38588,28#ec gdb packet code m sent 85 bytes (0 left) data (+$00E0226EFF7F00001F81A14A3B000000E0E3926DFF7F00005876D389707F00000080D389707F0000#2E) received gdb packet $m3b4aa1811c,4#86 gdb packet code m sent 13 bytes (0 left) data (+$20090A00#9C) received gdb packet $m7f7089d37658,28#e9 gdb packet code m sent 85 bytes (0 left) data (+$00000000000000004076D389707F0000B02A004D3B000000187BD389707F00008885D389707F0000#86) received gdb packet $m7f7089d37640,4#aa gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m7f7089d37644,4#ae gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m7f7089d37648,4#b2 gdb packet code m sent 13 bytes (0 left) data (+$69627465#AD) received gdb packet $m7f7089d3764c,4#dd gdb packet code m sent 13 bytes (0 left) data (+$726D6361#B3) received gdb packet $m7f7089d37650,4#ab gdb packet code m sent 13 bytes (0 left) data (+$702E736F#C4) received gdb packet $m7f7089d37654,4#af gdb packet code m sent 13 bytes (0 left) data (+$2E320000#9C) received gdb packet $m7f7089d37b18,28#11 gdb packet code m sent 85 bytes (0 left) data (+$0000000000000000007BD389707F0000A02D804B3B0000000040D289707F00005876D389707F0000#74) received gdb packet $m7f7089d37b00,4#d2 gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m7f7089d37b04,4#d6 gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m7f7089d37b08,4#da gdb packet code m sent 13 bytes (0 left) data (+$6962646C#BA) received gdb packet $m7f7089d37b0c,4#05 gdb packet code m sent 13 bytes (0 left) data (+$2E736F2E#D4) received gdb packet $m7f7089d37b10,4#d3 gdb packet code m sent 13 bytes (0 left) data (+$32000000#85) received gdb packet $m7f7089d24000,28#d2 gdb packet code m sent 85 bytes (0 left) data (+$0000000000000000C07FD389707F000060FB144B3B000000E8C4C14A3B000000187BD389707F0000#BA) received gdb packet $m7f7089d37fc0,4#09 gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m7f7089d37fc4,4#0d gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m7f7089d37fc8,4#11 gdb packet code m sent 13 bytes (0 left) data (+$6962632E#B7) received gdb packet $m7f7089d37fcc,4#3c gdb packet code m sent 13 bytes (0 left) data (+$736F2E36#C6) received gdb packet $m7f7089d37fd0,4#0a gdb packet code m sent 13 bytes (0 left) data (+$00000000#80) received gdb packet $m3b4ac1c4e8,28#f5 gdb packet code m sent 85 bytes (0 left) data (+$0000000000000000380240000000000008BEC14A3B000000D0628C00000000000040D289707F0000#04) received gdb packet $m400238,4#fe gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m40023c,4#29 gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m400240,4#f7 gdb packet code m sent 13 bytes (0 left) data (+$642D6C69#C8) received gdb packet $m400244,4#fb gdb packet code m sent 13 bytes (0 left) data (+$6E75782D#CC) received gdb packet $m400248,4#ff gdb packet code m sent 13 bytes (0 left) data (+$7838362D#B9) received gdb packet $m40024c,4#2a gdb packet code m sent 13 bytes (0 left) data (+$36342E73#B1) received gdb packet $m400250,4#f8 gdb packet code m sent 13 bytes (0 left) data (+$6F2E3200#B8) received gdb packet $m8c62d0,28#9a gdb packet code m sent 85 bytes (0 left) data (+$00905486707F0000D0588C0000000000F82D7586707F00000000000000000000E8C4C14A3B000000#64) received gdb packet $m8c58d0,4#69 gdb packet code m sent 13 bytes (0 left) data (+$2F6C6962#C8) received gdb packet $m8c58d4,4#6d gdb packet code m sent 13 bytes (0 left) data (+$36342F6C#C1) received gdb packet $m8c58d8,4#71 gdb packet code m sent 13 bytes (0 left) data (+$69626E73#BC) received gdb packet $m8c58dc,4#9c gdb packet code m sent 13 bytes (0 left) data (+$735F6669#C0) received gdb packet $m8c58e0,4#6a gdb packet code m sent 13 bytes (0 left) data (+$6C65732E#C5) received gdb packet $m8c58e4,4#6e gdb packet code m sent 13 bytes (0 left) data (+$736F2E32#C2) received gdb packet $m8c58e8,4#72 gdb packet code m sent 13 bytes (0 left) data (+$00588C00#A8) received gdb packet $m3b4ac1cc60,4#b7 gdb packet code m sent 13 bytes (0 left) data (+$01000000#81) received gdb packet $m3b4ac1cc68,8#c3 gdb packet code m sent 21 bytes (0 left) data (+$0080D389707F0000#54) received gdb packet $m3b4ac1cc70,8#bc gdb packet code m sent 21 bytes (0 left) data (+$F0D9A04A3B000000#6E) received gdb packet $m49c0f0,8#67 gdb packet code m sent 21 bytes (0 left) data (+$B5DC490000000000#4B) received gdb packet $Z0,3b4aa0d9f0,1#01 gdb packet code Z sent 5 bytes (0 left) data (+$#00) received gdb packet $m3b4aa0d9f0,1#b8 gdb packet code m sent 7 bytes (0 left) data (+$F3#79) received gdb packet $X3b4aa0d9f0,0:#dc gdb packet code X sent 5 bytes (0 left) data (+$#00) received gdb packet $M3b4aa0d9f0,1:cc#98 gdb packet code M sent 7 bytes (0 left) data (+$OK#9A) received gdb packet $vCont?#49 gdb packet code v sent 5 bytes (0 left) data (+$#00) received gdb packet $Hc0#db gdb packet code H sent 5 bytes (0 left) data (+$#00) received gdb packet $c#63 gdb packet code c sent 1 bytes (0 left) data (+) report_quiesce 4870 event 0x0 0x5->0x5 report_quiesce 4870 event 0x4 0x5->0x5 report_clone 4870->4950 report_signal 4870 (0x5) kern 1 skip 0 stop 0 action 0x0 sent 7 bytes (0 left) data ($S11#B5) report_signal 4870 (0x75) kern 1 skip 0 stop 0 action 0x75 received gdb packet $g#67 gdb packet code g report_quiesce 4870 event 0x0 0x5->0x0 sent 1093 bytes (0 left) data (+$00000000000000000000000000000000FFFFFFFFFFFFFFFF40558F6DFF7F000070568F6DFF7F00001100000000000000000000000000000038558F6DFF7F0000C0B4A40000000000000000000000000008000000000000004602000000000000000000000000000000000000000000000100000000000000D0B3A30000000000806043000000000046020000330000002B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000<7>received gdb packet $M3b4aa0d9f0,1:f3#6b ##################################################################################### NOTE: dmesg output printed by enabling DEBUG also shows that stub neither received packets from client about whether it should continue or stop or step when signal SIGCHLD i.e S11 was received. ##################################################################################### gdb packet code M sent 7 bytes (0 left) data (+$OK#9A) received gdb packet $m3b4aa0d9f0,1#b8 gdb packet code m sent 7 bytes (0 left) data (+$F3#79) received gdb packet $M3b4aa0d9f0,1:cc#98 gdb packet code M sent 7 bytes (0 left) data (+$OK#9A) received gdb packet $C11#a5 gdb packet code C sent 1 bytes (0 left) data (+) report_signal 4870 (0x5) kern 1 skip 1 stop 0 action 0x5 report_quiesce 4870 event 0x10 0x5->0x5 report_exit 4870 (0) sent 7 bytes (0 left) data ($W00#B7) gdb 4870 releasing current From elcher at jubagagg.com Mon Jul 13 18:32:16 2009 From: elcher at jubagagg.com (Arabella Coleman) Date: Mon, 13 Jul 2009 20:32:16 +0200 Subject: Nice things for your health are waiting for you! Message-ID: <20090713203216.4070202@jubagagg.com> Great offers today http://jy.wlumowur.cn/ From brocaded at urkoz.com Tue Jul 14 03:36:15 2009 From: brocaded at urkoz.com (Supernaw) Date: Tue, 14 Jul 2009 03:36:15 -0000 Subject: elusive Message-ID: <213b9b845e20090714033212@urkoz.com> The 5 sex Foreplay Stemps For Giiving Her a Mind Blowing Orgasm.www+nu26+com From shachar at shemesh.biz Tue Jul 14 06:53:00 2009 From: shachar at shemesh.biz (Shachar Shemesh) Date: Tue, 14 Jul 2009 09:53:00 +0300 Subject: Where has GETSIGINFO gone? In-Reply-To: <20090713155521.GA16733@caradoc.them.org> References: <4A584857.3040709@shemesh.biz> <20090713155521.GA16733@caradoc.them.org> Message-ID: <4A5C2B4C.4030306@shemesh.biz> Daniel Jacobowitz wrote: > On Sat, Jul 11, 2009 at 11:07:51AM +0300, Shachar Shemesh wrote: > >> The problem is that, as a debugger, I need to be able to >> differentiate between a SIGTRAP supposedly delivered to the debuggee >> because I asked to trace the system calls, and a SIGTRAP actually >> delivered to the debuggee. If I don't, my count is going to be off, >> and I will totally mis-interpret the debugee's state. >> >> The best way, as far as I can tell, to do that on Linux is to use the >> PTRACE_GETSIGINFO command. This provides me with a field, si_code, >> that can distinguish between a signal and a system call. This is >> important to make sure that I don't get confused over which is which. >> > > Have you seen PTRACE_SETOPTIONS and PTRACE_O_TRACESYSGOOD? > > Hi Daniel, Yes, I have, and the last sentence in the relevant paragraph from the ptrace(2) manual page scares me no end: > PTRACE_O_TRACESYSGOOD (since Linux 2.4.6) > When delivering syscall traps, set bit 7 in the > signal number (i.e., deliver (SIGTRAP | 0x80) This makes > it easy for the tracer to tell the difference > between normal traps and those caused by a syscall. > (PTRACE_O_TRACESYSGOOD may not work on all > architectures.) Admittedly, I tried to find out where the "5" was coming from for GETSIGINFO (as the user space headers only define 1 and 2, and the kernel headers define 1-4). After some research, it appears that the vanilla kernel's "5" si_code report just happens to be the value of SIGTRAP (the actual code is at includes/tracehook.h in the ptrace_report_syscall function, the call to the ptrace_notify function places the value into si_code). In other words, not the most reliable in the world either. The bottom line is that it does not matter much. Between the platform's inconsistency (single step reports 1 on i686, 2 on amd64), the randomness that is the si_code for syscall tracing, and the fact that you can ask for single step OR be notified of syscalls, but not both, the only conclusion is that there are two valid values for si_code: 0 means a standard signal (including the one generated after an execve), and anything else is a trace/trap/syscall/singlestep, based on what you asked to do. At least for fakeroot-ng, that is good enough. Don't get me wrong. This is a horrible mess. Then again, particularly on this list, I'm certain I'm not saying anything new to any of you when I say ptrace is a mess. The thing is, it is usable. Getting back to the matters at hand, the utrace behavior is simply incorrect. EINVAL is supposed to mean that I passed an invalid value to the system call. For GETSIGINFO, it means that the kernel is passing invalid values to me. This should never happen. Shachar -- Shachar Shemesh Lingnu Open Source Consulting Ltd. http://www.lingnu.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From cohen at smamd.com Tue Jul 14 11:44:37 2009 From: cohen at smamd.com (Clement Mercer) Date: Tue, 14 Jul 2009 12:44:37 +0100 Subject: Find way to immense pleasure Message-ID: <20090714124437.8010105@smamd.com> She'll reward you so much http://knu.qwyqugtop.com/ From drow at false.org Tue Jul 14 13:01:37 2009 From: drow at false.org (Daniel Jacobowitz) Date: Tue, 14 Jul 2009 09:01:37 -0400 Subject: Where has GETSIGINFO gone? In-Reply-To: <4A5C2B4C.4030306@shemesh.biz> References: <4A584857.3040709@shemesh.biz> <20090713155521.GA16733@caradoc.them.org> <4A5C2B4C.4030306@shemesh.biz> Message-ID: <20090714130137.GA25353@caradoc.them.org> On Tue, Jul 14, 2009 at 09:53:00AM +0300, Shachar Shemesh wrote: > Yes, I have, and the last sentence in the relevant paragraph from the > ptrace(2) manual page scares me no end: > > PTRACE_O_TRACESYSGOOD (since Linux 2.4.6) > > When delivering syscall traps, set bit 7 in > >the signal number (i.e., deliver (SIGTRAP | 0x80) This makes > > it easy for the tracer to tell the difference > >between normal traps and those caused by a syscall. > > (PTRACE_O_TRACESYSGOOD may not work on all > >architectures.) The man page is pretty old. It should work everywhere nowadays. -- Daniel Jacobowitz CodeSourcery From rambles at bkg.lv Tue Jul 14 16:01:37 2009 From: rambles at bkg.lv (rambles) Date: Tue, 14 Jul 2009 16:01:37 +0000 Subject: argosy Message-ID: <2A0786E7398F92CF43CAFCC81038C5FF2E705A@bkg.lv> How to Turn a Woman On - Make Her Beg You to Gfet Into eBd With Her.www .te81. net From isomerizes at cnica.cu Wed Jul 15 03:26:21 2009 From: isomerizes at cnica.cu (Lias) Date: Wed, 15 Jul 2009 03:26:21 -0000 Subject: hang Message-ID: <15206cda51c720090715032055@cnica.cu> Gijve Her Multiple Orgasms - oHw to Make a Woman Scream Your Name.www-ze44-com From phanerophyte at asticon.dk Thu Jul 16 01:49:28 2009 From: phanerophyte at asticon.dk (phanerophyte) Date: Thu, 16 Jul 2009 01:49:28 +0000 Subject: anteroom Message-ID: <0e2a.Nul5NS0KR5n9v@asticon.dk> Problems in Gettivng hte sex Life You Want and Deserve - Starting With F.www[dot]ba43[dot]com From oleg at redhat.com Thu Jul 16 05:59:48 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 16 Jul 2009 07:59:48 +0200 Subject: Q: utrace_stop() && notification Message-ID: <20090716055948.GA31266@redhat.com> If ->report_xxx() returns UTRACE_STOP the tracee will do utrace_stop eventually. But how can the tracer know the tracee is already TASK_TRACED/->stopped? (except it can check utrace_control(UTRACE_STOP) in a loop of course). Actually, I am asking because this chunk from utrace-ptrace.patch +#ifdef CONFIG_UTRACE_PTRACE + /* + * If ptrace is among the reasons for this stop, do its + * notification now. This could not just be done in + * ptrace's own event report callbacks because it has to + * be done after we are in TASK_TRACED. This makes the + * synchronization with ptrace_do_wait() work right. + */ + if (((task->ptrace >> 16) & UTRACE_RESUME_MASK) == + UTRACE_RESUME - UTRACE_STOP) { + read_lock(&tasklist_lock); + do_notify_parent_cldstop(task, CLD_TRAPPED); + read_unlock(&tasklist_lock); + } +#endif Looks like a horrible hack, imho. Utrace should know nothing about ptrace. Can't we do something like --- include/linux/utrace.h +++ include/linux/utrace.h @@ -170,6 +170,7 @@ void task_utrace_proc_status(struct seq_ */ enum utrace_resume_action { UTRACE_STOP, + UTRACE_STOP_NOTIFY, UTRACE_REPORT, UTRACE_INTERRUPT, UTRACE_SINGLESTEP, @@ -512,6 +513,9 @@ static inline void utrace_engine_put(str * parent by blocking. */ struct utrace_engine_ops { + // SPECIAL!!! must not block/etc + void (*notify_stopped)(...); + u32 (*report_quiesce)(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *task, --- kernel/utrace.c +++ kernel/utrace.c @@ -419,6 +419,13 @@ static bool utrace_stop(struct task_stru spin_unlock_irq(&task->sighand->siglock); spin_unlock(&utrace->lock); + list_for_each_entry(engine) { + if (engine_wants_notify_stopped(engine)) { + clear_engine_wants_notify_stopped(engine); + engine->ops->notify_stopped(...); + } + } + schedule(); @@ -1348,6 +1355,11 @@ static bool finish_callback(struct utrac { enum utrace_resume_action action = utrace_resume_action(ret); + if (action == UTRACE_STOP_NOTIFY) { + mark_engine_wants_notify_stopped(engine); + action = UTRACE_STOP; + } + report->result = ret & ~UTRACE_RESUME_MASK; /* ? Or do you think this doesn't make sense? (of course, the "patch" above is just to explain what I mean, we need more changes with ENGINE_STOP mask, utrace_control, utrace_set_events, etc). Oleg. From contact at onedirect.cccampaigns.com Thu Jul 16 08:10:12 2009 From: contact at onedirect.cccampaigns.com (Onedirect) Date: Thu, 16 Jul 2009 10:10:12 +0200 (CEST) Subject: 24h pour profiter de votre offre exceptionnelle Message-ID: <31155884909.5813718.1247731812191@schr3> Bonjour, si vous n'arrivez pas à lire ce message, visualisez la version en ligne : http://trc1.emv2.com/HM?a=A9X7Cq5nhCKC8XiI5q1Pa0_jMQ. Vous recevez ce courriel sur l'adresse utrace-devel at redhat.com. Pour être sûr de recevoir correctement nos courriels, ajoutez l'adresse caroline at onedirect.fr à votre carnet d'adresse. Découvrez toute la gamme de téléphonie pro : http://trc1.emv2.com/HU?a=A9X7Cq5nhCKC8XiI5q1Pa0LjNA Casque, Kit Bluetooth, Téléphone sans fil, Téléphone filaire, Mini-standard, Talkie Walkie, Téléconférence, Enregistreurs. Une équipe formée et disponible vous conseille. Plus de 100 000 clients nous font confiance depuis 1999, 1800 références en stock permanent. 96% des commandes expédiées le jour même. Appelez le 08 26 10 11 12 0,15ttc/mn Ce courriel commercial est conforme à la législation en vigueur et aux délibérations de la CNIL des 22 et 30 mars 2005 sur la prospection par courrier électronique dans le cadre professionnel. Conformément à l'article 34 de la loi 78-17 du 6 janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés, vous disposez d'un droit d'accès, de rectification des données nominatives vous concernant. Si vous ne souhaitez plus recevoir d'informations commerciales de notre société par e-mail, Désabonnez vous : http://trc1.emv2.com/HP?a=A9X7Cq5nhCKC8XiI5q1Pa0zjMg. Le présent message est en parfait respect avec la déontologie et les bonnes pratiques de la communication par marketing direct électronique. Conformément à la législation en vigueur et des différents rectificatifs légaux, vous disposez d'un plein droit d'accès, de modifications ou de suppression des données personnelles vous concernant. Vous pouvez à tout moment excécer se droit sur demande écrite ou via notre espace prévu à cet effet. Conformément à la loi Informatique et libertés, vous pouvez vous désabonner à tout moment. Pour toute autre demande n'hésitez pas à nous écrire (Afin de faciliter le traitement de votre envoi, précisez votre demande dans l'objet et le corps du message). Loi n° 78-17 du 6 Janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une nécessité légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement de la publicité par voie électronique. Art 38 : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une obligation légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement. Cet e-mail vous a été envoyé par OneDirect qui peut être amenée à recourir à ses sociétés affiliées afin de vous fournir ses services. Vos préférences de notification indiquent que vous souhaitez recevoir des informations sur les promotions, les offres spéciales et certaines manifestations. OneDirect ne vous demandera JAMAIS de fournir par e-mail des informations personnelles telles que les mots de passe. Vous êtes inscrit(e) en utilisant l'adresse utrace-devel at redhat.com indiquée lors de votre inscription sur notre site. Si vous ne souhaitez plus recevoir de propositions commerciales de notre part, il vous suffit de vous rendre sur le site, et de changer vos préférences de notification par email à caroline at onedirect.fr. Copyright © 2008 OneDirect. Tous droits réservés. Les marques et marques commerciales mentionnées appartiennent à leurs propriétaires respectifs. -------------- next part -------------- An HTML attachment was scrubbed... URL: From leeds at cosmos-jesi.com Thu Jul 16 14:23:44 2009 From: leeds at cosmos-jesi.com (Rosa) Date: Thu, 16 Jul 2009 14:23:44 +0000 Subject: passwords Message-ID: <200907161417189908533cripple@cosmos-jesi.com> Make Your Lover Have Multiple Orgasms Thrtough Intercourse Alone - She'll Never Think off Cheating!.www[dot]pe48[dot]com From journeybiz at ymail.com Thu Jul 16 20:32:29 2009 From: journeybiz at ymail.com (=?iso-8859-1?Q?journeybiz@ymail=2Ecom?=) Date: Fri, 17 Jul 2009 06:32:29 +1000 Subject: Heard about Golden Glow?... Message-ID: <20090716203229.EFF3411D36@syd1-0003mr.server-mail.com> Hi There, Online Income Seeker, Discover The Most Effective Step-By-Step Money Making System In Existence... "This System Makes Me At Least $171,168.06 Per Month And You Can Start Using It 15 Minutes From Now"... Just Hit The Link Below... http://go2-url.com/anezee http://2d15d92gyljrg4bapfqoy7x-cv.hop.clickbank.net To Your Success, Journey Biz journeybiz at ymail.com From roland at redhat.com Thu Jul 16 23:35:17 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 16 Jul 2009 16:35:17 -0700 (PDT) Subject: Q: utrace_stop() && notification In-Reply-To: Oleg Nesterov's message of Thursday, 16 July 2009 07:59:48 +0200 <20090716055948.GA31266@redhat.com> References: <20090716055948.GA31266@redhat.com> Message-ID: <20090716233517.BA7A44702D@magilla.sf.frob.com> > If ->report_xxx() returns UTRACE_STOP the tracee will do utrace_stop > eventually. But how can the tracer know the tracee is already > TASK_TRACED/->stopped? We don't really have a way. It is something we need to address better. This is the most essential thing that made the old utrace-ptrace.patch a temporary kludge rather than a good model. > Looks like a horrible hack, imho. Utrace should know nothing about > ptrace. Agreed! > Can't we do something like [...] > + // SPECIAL!!! must not block/etc > + void (*notify_stopped)(...); Part of the point about utrace is to make it easier not to foul up other engines when your engine has a bug. Many of the rules about well-behaved callbacks have to be met by all engines or they will interfere; we can't really avoid that reality when we call engines' code. But part of the plan is not to make those rules too hard to meet. That's why the "don't block (for long)" rule is such a loose constraint in real kernel terms. Having engine-writers commonly need to write code that can't even call mutex_lock or kalloc, etc., is IMHO just too much to ask. It's far better if we don't have such tight constraints on any callback that engine-writers will really need to use, if even if just this special case. (Because it really is not a rare thing--this is the essential kind of synchronization that any engine-writer who handles stopping at all will want.) The report_* callback is the engine's opportunity to synchronize with its asynchronous engine code (debugger threads, etc.). The crux of the issue is that when your "synchronizing" callback is done, there always might be another engine's callback running afterwards. Hence, the actual effect of UTRACE_STOP causing TASK_TRACED state doesn't happen until after the callback. So your synchronization partner then really needs a second synchronization with the thread itself really stopping. Let's talk about the utrace API semantics picture for this purely from the engine-writer's point of view for a bit before we get into the implementation details inside utrace. The pieces we have now are engines doing their own wakeups in callbacks, utrace_barrier, and utrace_prepare_examine. Currently utrace_barrier only makes guarantees about the ordering of callbacks and the various asynchronous utrace_* calls, but not about true thread stoppedness. utrace_prepare_examine verifies that the target is blocked already, and synchronizes with low-level context switch details for that, but does not do any synchronization/delay *before*/with target->state entering its blocked/stopped state. Note it does not in particular require the target be stopped, though does require the caller's engine used UTRACE_STOP. This is intended for non-perturbing examination of a thread that might be blocked in a syscall (a la task_current_syscall). But as it stands, it would also try to accept a thread that is just blocked in kalloc/mutex_lock in the next engine's callback. But unlike the syscall, that is likely to actually wake up again very soon and that results in an -EAGAIN hiccup from utrace_prepare_examine or utrace_finish_examine. So in today's utrace, the best you can do is: report_* does: wake_up(you); return UTRACE_STOP; you wake up and do: utrace_barrier => your callback is finished, its UTRACE_STOP is logged utrace_prepare_examine => if ok, it's really stopped now |> if -EAGAIN, you have to loop(?) user_regset->get, etc. (aka arch_ptrace) utrace_finish_examine => if ok, it really was really stopped when i said it was |> if -AGAIN, you have to loop(?) A first notion is to give utrace_barrier a stronger guarantee: when your engine has UTRACE_STOP in force and then you call utrace_barrier, it blocks until the target enters a truly stopped state. But OTOH that is *too* strong if what you want is to see ASAP what the thread is doing, be it properly stoppable now or blocked in a syscall you don't want to interrupt. I guess maybe if you want to get a thing positively stopped as distinct from maybe-just-blocked-in-syscall (but with UTRACE_STOP preventing it from reaching userland), then you should just start out by using utrace_control(,,UTRACE_INTERRUPT) (perhaps followed by utrace_control(,,UTRACE_STOP) to get "already stopped" return value?) and have your callback return UTRACE_STOP. So then perhaps instead what makes sense is that utrace_prepare_examine should roll in an actual synchronization waiting for target->state to be blocked outside of any other utrace engine callbacks (after them all). If you want to do a "non-blocking" asynchronous sample of a thread, then it's safe to use this only after your engine callback has notified you that UTRACE_STOP is in force or utrace_control(,,UTRACE_STOP) returned zero. Or perhaps we can make it so utrace_prepare_examine diagnoses the "waiting for utrace to settle down" and the "real blocks" differently. The point there is that a "non-blocking sample" doesn't want to have a window where the debugger saw the target was starting to block in some real kernel code (had changed ->state) but then the debugger winds up blocking after ther target has woken again and then runs for a long time in the kernel without a block. (In that case, the debugger should see "it's still running a lot, you will get your callback eventually".) A related issue to keep in mind in all this is the "preemption flutter" problem that someone cited with ptrace (it was biting UML folks, you may recall). The control flow in old ptrace is simple enough that we could defuse that adequately just by omitting an explicit preemption check or two so that voluntary preemption would not tend to occur between the tracer wakeup and the actual schedule() blocking the tracee. In the utrace world, there will be far more going on and it would be unlikely we could manage that approach for long. Moreover, a core tenet of utrace is to help tracing engines not clog the system up generally, so IMHO we very much want extra preemption checks between callbacks and the like (as we have now in finish_callback). So we'd really like to address that sort of problem with really proper synchronization between what in the tracer really needs to wait for what in the tracee, rather than more of the juggled-together-but-not-actually-tied dances going on now. Working in the other direction, we have the (my) idea in utrace that no particular operation should be any more synchronous than it has to be. This motivates the approach of low-level moving parts the engine-writer fits together, the only blocking synchronizations being explicit calls like utrace_barrier, etc. So, what does it all mean? Well, I don't know exactly. It means that I feel strongly about retaining the flexibility in utrace to do things in very asynchronous and opportunistic ways, and I want to keep the core API focus on a fairly small number of calls. At the same time we need to do something that really makes good sense both for ptrace and for other engines that will have a similarly synchronous sort of control flow but different (and I hope less idiosyncratic) means to synchronize with debugger calls. I have a thought or two about ptrace in particular. But perhaps first we can explore the general case of the synchronization picture in the API some. Thanks, Roland From srikar at linux.vnet.ibm.com Fri Jul 17 05:39:17 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Fri, 17 Jul 2009 11:09:17 +0530 Subject: [RESEND] [PATCH 0/7] Ubp, Ssol and Uprobes In-Reply-To: <20090611160539.GA20668@linux.vnet.ibm.com> References: <20090611160539.GA20668@linux.vnet.ibm.com> Message-ID: <20090717053917.GA25407@linux.vnet.ibm.com> Hi Roland, et al, Did you get a chance to review this patchset? I was planning to post to LKML after addressing comments from you. -- Thanks and Regards Srikar > Hi, > > This patchset implements uprobes over utrace. > Please review the patchset and provide your valuable comments. > These patches have been tested on the current utrace tree(commit id > cf890ad46816982f3b8b5064d2f2bb91968ded43) > > This patchset requires Roland's utrace implementation + > Jim and Masami's x86 instruction analysis layer. > > Patches 1 to 6 implement uprobes > Patch 7 implements ftrace plugin > > Based on your feedback, I was looking at posting these patches to > LKML some time next week. > > [PATCH 0/7] Ubp, Ssol and Uprobes > [PATCH 1/7] User Space Breakpoint Assistance Layer (UBP) > [PATCH 2/7] x86 support for UBP > [PATCH 3/7] Execution out of line (XOL) > [PATCH 4/7] Uprobes Implementation > [PATCH 5/7] x86 support for Uprobes > [PATCH 6/7] Uprobes documentation. > [PATCH 7/7] Ftrace plugin for Uprobes. > > -- > Thanks and Regards > Srikar From info at canal-marketing.com Fri Jul 17 07:55:00 2009 From: info at canal-marketing.com (=?ISO-8859-1?Q?IC_Telecom?=) Date: Fri, 17 Jul 2009 09:55:00 +0200 Subject: Illimite : Communications - Internet - telephones Message-ID: An HTML attachment was scrubbed... URL: From roofless at plan-large.com Fri Jul 17 16:14:57 2009 From: roofless at plan-large.com (roofless) Date: Fri, 17 Jul 2009 15:14:57 -0100 Subject: fieri Message-ID: <7A2D7C@plan-large.com> French Kissing -- Women Love It Learn How Too Do It Correctly!.www[dot]pill84[dot]net From uncanonised at worum.no Sat Jul 18 16:01:22 2009 From: uncanonised at worum.no (uncanonised) Date: Sat, 18 Jul 2009 16:01:22 -0000 Subject: wont Message-ID: <37E6DEDF2D9171FB3DE8BF720608F7C56B6EDD@worum.no> How Too Get Dumped In Bed Within Minutes - Top 33 Mistakes Most Men Make In Bed.www[dot]meds35[dot]net From tautologies at kosin.fo Sun Jul 19 04:48:44 2009 From: tautologies at kosin.fo (tautologies) Date: Sun, 19 Jul 2009 04:48:44 -0000 Subject: hoodlumism Message-ID: oHw too Cope With Gender Dysphoria.www[dot]33211[dot]org From kludgers at beanimation.com Sun Jul 19 16:55:42 2009 From: kludgers at beanimation.com (Traff Walund) Date: Sun, 19 Jul 2009 16:55:42 +0000 Subject: amoralism Message-ID: Feminization Hyypnosis - Unleashing the Womman Within.www[dot]21113[dot]org From foxing at ablesoft.com Mon Jul 20 05:47:10 2009 From: foxing at ablesoft.com (foxing) Date: Mon, 20 Jul 2009 05:47:10 -0000 Subject: audiotypist Message-ID: <34413288788493909395@ablesoft.com> Really Simple Seduction Tips! The Fastest Way to Seudce a Woman (These Raelly Work!).www[dot]za16[dot]com From oleg at redhat.com Mon Jul 20 15:26:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 20 Jul 2009 17:26:52 +0200 Subject: Q: utrace_stop() && notification In-Reply-To: <20090716233517.BA7A44702D@magilla.sf.frob.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> Message-ID: <20090720152652.GA17395@redhat.com> On 07/16, Roland McGrath wrote: > > > Looks like a horrible hack, imho. Utrace should know nothing about > > ptrace. > > Agreed! > > > Can't we do something like > [...] > > + // SPECIAL!!! must not block/etc > > + void (*notify_stopped)(...); > > Part of the point about utrace is to make it easier not to foul up other > engines when your engine has a bug. Many of the rules about well-behaved > callbacks have to be met by all engines or they will interfere; we can't > really avoid that reality when we call engines' code. > > But part of the plan is not to make those rules too hard to meet. > That's why the "don't block (for long)" rule is such a loose constraint > in real kernel terms. Having engine-writers commonly need to write code > that can't even call mutex_lock or kalloc, etc., is IMHO just too much > to ask. It's far better if we don't have such tight constraints on any > callback that engine-writers will really need to use, if even if just > this special case. (Because it really is not a rare thing--this is the > essential kind of synchronization that any engine-writer who handles > stopping at all will want.) Yes, I see. That is why I named it "notify_stopped", not report_xxx, to emphasize it is really special and should be used with care and only when really needed. > So in today's utrace, the best you can do is: > > report_* does: > wake_up(you); > return UTRACE_STOP; > you wake up and do: > utrace_barrier > => your callback is finished, its UTRACE_STOP is logged > utrace_prepare_examine > => if ok, it's really stopped now > |> if -EAGAIN, you have to loop(?) > user_regset->get, etc. (aka arch_ptrace) > utrace_finish_examine > => if ok, it really was really stopped when i said it was > |> if -AGAIN, you have to loop(?) > > [... snip a lot of great explanations ...] Thanks Roland. I even printed your message to re-read it carefully. But there is another another reason why (I think) utrace_stop should not play with ptrace/do_notify_parent_cldstop. The usage of ->ptrace in utrace-ptrace is racy wrt attach/detach which sets/clears ->ptrace. Only ptracer should change ->ptrace. Just for example. If the tracee dequeues a signal right after PTRACE_ATTCH does prepare_ptrace_attach(), then ptrace_set_action() can race with ptrace_attach() doing "task->ptrace = PT_PTRACED". I think we need another variable which should be used instead, and the only "good" place where it can live is engine->data, it should point to "struct ptrace_xxx". So, if we do not want to add the special (and not-a-report) hooks into engine->ops, then perhaps it makes sense to do utrace_stop: if (task_is_ptraced(task)) ptrace_utrace_stop(task); void ptrace_utrace_stop(struct task_struct *task) { if (ptrace_resume_action(task) != UTRACE_STOP) return; read_lock(&tasklist_lock); do_notify_parent_cldstop(task, CLD_TRAPPED); read_unlock(&tasklist_lock); } But, even with the code above it is not easy to move the "task->ptrace >> 16" info into engine->data, we have to find the engine first which looks a bit ugly. And even utrace_stop()->task_is_ptraced() does not look very nice. So, perhaps we can just add engine->ops->notify_stopped() (or even ->ptrace_notify_stopped) without introducing UTRACE_STOP_NOTIFY, utrace_stop() just calls this hook unconditionally if it != NULL. Oleg. From oleg at redhat.com Mon Jul 20 17:22:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 20 Jul 2009 19:22:40 +0200 Subject: Q: utrace && ptrace_check_attach() Message-ID: <20090720172240.GA22459@redhat.com> First of all, I believe ptrace_check_attach() is buggy. It lacks "child->parent == current" or "engine->data == current" check. The bug is serious, sys_ptrace() does not do security checks unless request == PTRACE_ATTACH. But this is trivial to fix. Also. Without utrace, ptrace_check_attach() requires the child is STOPPED or TRACED. With utrace, ptrace_check_attach() does utrace_control(UTRACE_STOP) first. If the child is not stopped we return -ESRCH correctly, but utrace_control() sets ENGINE_STOP and utrace->report, and this can actually stop the child. Yes, if ptracer does utrace_control(UTRACE_STOP), this doesn't necessarily mean the child will stop. But, for example, suppose that ptracer does sys_ptrace(WHATEVER) in a loop. In that case it is possible that utrace_control(UTRACE_STOP) races with the child doing utrace_resume()->start_callback(), and we can set ENGINE_STOP right before start_callback() re-reads engine->flags under "if (want & UTRACE_EVENT(QUIESCE))". This is minor, but not good anyway. Unless I missed something. And. From another thread, utrace_prepare_examine verifies that the target is blocked already, ... Note it does not in particular require the target be stopped, though does require the caller's engine used UTRACE_STOP. Yes, but I am a bit worried about ptrace_check_attach() case... For example, utrace_control(UTRACE_STOP)->utrace_do_stop() finds the child inside utrace_report_jctl() path in TASK_STOPPED state, sets utrace->stopped and returns true. After that utrace_report_jctl() clears ->stopped and another engine's ->report_jctl does mutex_lock() and sets ->state == TASK_INTERRUPTIBLE. This means that ptrace_check_attach() can succeed while the child can be waked up soon and do a lot more before it actually stops. I don't see really bad implications though, just worried. Oleg. From oleg at redhat.com Mon Jul 20 19:38:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 20 Jul 2009 21:38:36 +0200 Subject: Q: utrace_prepare_examine() && get_task_struct(target) Message-ID: <20090720193836.GA7350@redhat.com> I fail to understand rcu_read_lock() + get_task_struct() in utrace_prepare_examine(). This looks as if the caller does not need to make sure task_struct can't go away. But, unless the caller does get_task_struct() itself (like ptrace does), utrace_prepare_examine() can race with utrace_reap() (if the tracee is killed) which detaches the engine but doesn't clear engine->flags ? Oleg. From roland at redhat.com Tue Jul 21 03:00:37 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 20 Jul 2009 20:00:37 -0700 (PDT) Subject: Q: utrace_prepare_examine() && get_task_struct(target) In-Reply-To: Oleg Nesterov's message of Monday, 20 July 2009 21:38:36 +0200 <20090720193836.GA7350@redhat.com> References: <20090720193836.GA7350@redhat.com> Message-ID: <20090721030037.A6A7B6D02E@magilla.sf.frob.com> The utrace_*_examine calls have been neither used nor examined much at all (no pun intended). So both the API and the implementation for these can use a fresh look and reconsideration. Also, this is somewhat intimately tied up with the broader synchronization picture. So it might make most sense not to spend much effort hashing out microdetails of *_examine until we are doing it in the context of having hashed more out about the general subject of synchronization. > I fail to understand rcu_read_lock() + get_task_struct() in > utrace_prepare_examine(). This looks as if the caller does not need to > make sure task_struct can't go away. That's kind of the idea. (See below.) > But, unless the caller does get_task_struct() itself (like ptrace does), > utrace_prepare_examine() can race with utrace_reap() (if the tracee is > killed) which detaches the engine but doesn't clear engine->flags ? Yeah, it might just need this: diff --git a/kernel/utrace.c b/kernel/utrace.c index 74b5fc5..60af805 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -549,6 +549,7 @@ restart: list_for_each_entry_safe(engine, next, &utrace->attached, entry) { ops = engine->ops; engine->ops = NULL; + engine->flags = 0; list_move(&engine->entry, &detached); /* @@ -580,6 +581,12 @@ restart: spin_unlock(&utrace->lock); put_detached_list(&detached); + + /* + * Make sure all engine->flags and engine->ops updates are done + * before the current task_struct might really die. + */ + smp_wmb(); } /* @@ -2267,7 +2274,7 @@ int utrace_prepare_examine(struct task_struct *target, rcu_read_lock(); if (unlikely(!engine_wants_stop(engine))) ret = -EINVAL; - else if (unlikely(target->exit_state)) + else if (unlikely(smp_rmb(), target->exit_state)) ret = -ESRCH; else { exam->state = target->state; @@ -2320,7 +2327,7 @@ int utrace_finish_examine(struct task_struct *target, rcu_read_lock(); if (unlikely(!engine_wants_stop(engine))) ret = -EINVAL; - else if (unlikely(target->state != exam->state)) + else if (unlikely(smp_rmb(), target->state != exam->state)) ret = -EAGAIN; else get_task_struct(target); (but with a bit better commenting), or maybe that's not quite it either. Let me explain the general notion. It's always been a little iffy, and it definitely deserves an airing now in your fresh review of all things utrace. The root of the thing is that modules can't use get_task_struct(). More precisely, __put_task_struct is not exported (though it was once). But, the main use of utrace is from modules (probably everything but ptrace). One could argue upstream to export __put_task_struct again, but I wouldn't expect that whole discussion to be much fun. Even if not for the export issue, one could possibly argue that the utrace API does a service if it makes it difficult or impossible for a buggy utrace-using module to cause task_struct leaks. (That argument is a bit thin, I grant.) So, I've tried to address this in two different ways in the utrace API. One is the utrace_*_pid interfaces. put_pid() is exported, so modules can use get_pid/put_pid and only utrace_*_pid calls and never worry about task death races. (That is, all utrace_*_pid calls will safely return -ESRCH if the task disappears out from under the struct pid.) That approach was actually a later afterthought when I noticed that put_pid was exported. The other approach taken is still there too. That is, magic guarantees about utrace_* calls with valid engine pointers. The utrace calls take both a task_struct pointer and a utrace_engine pointer. If your engine pointer is valid, your task_struct pointer doesn't necessarily have to be. That is, they will safely return -ESRCH (or maybe some other particular error cases) if the task_struct disappears out from under the engine (including your code just asynchronously detaching the engine). So from the API perspective, modules have to maintain utrace_engine ref counts, and they can leak utrace_engine's if buggy. But if they get that right, just storing a task_struct pointer solely to pass it to utrace_* calls along with your engine pointer is safe without any other bookkeeping. The other calls use get_utrace_lock to implement this guarantee. It checks that your engine is attached before it looks at the task_struct, and this is (supposedly) synchronized with detach and reap safely. (You should be checking on that supposition, Oleg. ;-) Now we come to utrace_*_examine. These don't use get_utrace_lock, mostly just because I didn't think they needed that lock for any other reason. But the intent for the API was the same, and perhaps the patch above (or something along those lines) makes it an adequate implementation of that. But, this API is a bit dubious even if implemented correctly. (Here I mean just utrace_*_examine, though I'd see the point if someone wanted to characterize this whole task_struct pointer handling plan that way.) These API guarantees make each utrace_* call safe and atomic by itself. This seems pretty solidly useful for the others, which each complete a self-contained action on the task/engine state. Conversely, utrace_prepare_examine and utrace_finish_examine act as a pair with the point being to use the task_struct pointer for things in between. For a direct poke at task->thread.something you can make it work. rcu_read_lock(); ret = utrace_prepare_examine(task, engine, &exam); if (ret) goto hell; fiddle = task->faddle; rcu_read_unlock(); ret = utrace_finish_examine(task, engine, &exam); if (ret) goto hell; Even though utrace_prepare_examine (wait_task_inactive) will block and that lets RCU stuff happen, when you've come back again you will be in rcu_read_lock across the put_task_struct it does. So task is live until rcu_read_unlock(). (I have no idea if intentionally allowing a block inside rcu_read_lock freaks out lockdep or something.) But the case expected most is user_regset calls. You can't expect to call them safely without breaking rcu_read_lock. They are allowed to block, some call access_process_vm, etc. So how do you do that? This suggests perhaps utrace_prepare_examine ought to keep a task ref to be released by utrace_finish_examine. But then it's a back-door way for modules to use get/put_task_struct and leak task_structs. Is that OK? Otherwise, what else do we do instead? Do we have to provide utrace wrappers specifically for user_regset calls? It's not so bad that e.g. task_current_syscall() rolls it all in, but with user_regset there are three flavors of call, and you might really want to do several calls on one or more user_regsets, with some quick logic in between, etc. It could suck to do the whole wait_task_inactive cycle 2n times for n micro-level regset operations instead of just 2 times for the whole shebang. That's why I had the idea of the whole prepare/finish API model to begin with. So I think that's more or less the whole brain dump on utrace_*_examine and related subjects, except for any ideas about tying in differently to other kinds of synchronization. Thanks, Roland From unrealisable at jewometaal.com Tue Jul 21 05:36:54 2009 From: unrealisable at jewometaal.com (Pedralba Remmele) Date: Tue, 21 Jul 2009 06:36:54 +0100 Subject: knockout Message-ID: <71992C60702185546776@jewometaal.com> Arouse Yuor GG Spot and Your Partner.www[dot]via99[dot]org From contact at onedirect.cccampaigns.com Tue Jul 21 08:02:27 2009 From: contact at onedirect.cccampaigns.com (Onedirect / Gigaset) Date: Tue, 21 Jul 2009 10:02:27 +0200 (CEST) Subject: =?iso-8859-15?q?A_saisir_=3A_votre_Pack_libert=E9_Siemens_Gigase?= =?iso-8859-15?q?t?= Message-ID: <31155884909.5834024.1248163347437@schr3> Bonjour, si vous n'arrivez pas à lire ce message, visualisez la version en ligne : http://trc1.emv2.com/HM?a=A9X7Cq5nhCKC8Xk4GK1BIqzl3A. Vous recevez ce courriel sur l'adresse utrace-devel at redhat.com. Pour être sûr de recevoir correctement nos courriels, ajoutez l'adresse caroline at onedirect.fr à votre carnet d'adresse. Découvrez toute la gamme de téléphonie pro : http://trc1.emv2.com/HU?a=A9X7Cq5nhCKC8Xk4GK1BIqPl3w Casque, Kit Bluetooth, Téléphone sans fil, Téléphone filaire, Mini-standard, Talkie Walkie, Téléconférence, Enregistreurs. Une équipe formée et disponible vous conseille. Plus de 100 000 clients nous font confiance depuis 1999, 1800 références en stock permanent. 96% des commandes expédiées le jour même. Appelez le 08 26 10 11 12 0,15ttc/mn Ce courriel commercial est conforme à la législation en vigueur et aux délibérations de la CNIL des 22 et 30 mars 2005 sur la prospection par courrier électronique dans le cadre professionnel. Conformément à l'article 34 de la loi 78-17 du 6 janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés, vous disposez d'un droit d'accès, de rectification des données nominatives vous concernant. Si vous ne souhaitez plus recevoir d'informations commerciales de notre société par e-mail, Désabonnez vous : http://trc1.emv2.com/HP?a=A9X7Cq5nhCKC8Xk4GK1BIq3l3Q. Le présent message est en parfait respect avec la déontologie et les bonnes pratiques de la communication par marketing direct électronique. Conformément à la législation en vigueur et des différents rectificatifs légaux, vous disposez d'un plein droit d'accès, de modifications ou de suppression des données personnelles vous concernant. Vous pouvez à tout moment excécer se droit sur demande écrite ou via notre espace prévu à cet effet. Conformément à la loi Informatique et libertés, vous pouvez vous désabonner à tout moment. Pour toute autre demande n'hésitez pas à nous écrire (Afin de faciliter le traitement de votre envoi, précisez votre demande dans l'objet et le corps du message). Loi n° 78-17 du 6 Janvier mille neuf cent soixante dix huit, relative à l'informatique, aux fichiers et aux libertés : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une nécessité légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement de la publicité par voie électronique. Art 38 : Toute personne physique a le droit de s'opposer, pour des motifs légitimes, à ce que des données à caractère personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, à ce que les données la concernant soient utilisées à des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ultérieur. Les dispositions du premier alinéa ne s'appliquent pas lorsque le traitement répond à une obligation légale ou lorsque l'application de ces dispositions a été écartée par une disposition expresse de l'acte autorisant le traitement. Cet e-mail vous a été envoyé par OneDirect qui peut être amenée à recourir à ses sociétés affiliées afin de vous fournir ses services. Vos préférences de notification indiquent que vous souhaitez recevoir des informations sur les promotions, les offres spéciales et certaines manifestations. OneDirect ne vous demandera JAMAIS de fournir par e-mail des informations personnelles telles que les mots de passe. Vous êtes inscrit(e) en utilisant l'adresse utrace-devel at redhat.com indiquée lors de votre inscription sur notre site. Si vous ne souhaitez plus recevoir de propositions commerciales de notre part, il vous suffit de vous rendre sur le site, et de changer vos préférences de notification par email à caroline at onedirect.fr. Copyright © 2008 OneDirect. Tous droits réservés. Les marques et marques commerciales mentionnées appartiennent à leurs propriétaires respectifs. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ima.andrajl at paradigmhealth.org Tue Jul 21 12:00:32 2009 From: ima.andrajl at paradigmhealth.org (Ima Andra) Date: Tue, 21 Jul 2009 05:00:32 -0700 Subject: nmkg 9pwg In-Reply-To: <75eb01ca073c$82580920$933ae196@hy3oddq> Message-ID: <1248177632.4037@paradigmhealth.org> qcjj From hberniecezc at email.mot.com Tue Jul 21 12:02:38 2009 From: hberniecezc at email.mot.com (Hildegarde Berniece) Date: Tue, 21 Jul 2009 05:02:38 -0700 Subject: ckllo ejo In-Reply-To: Message-ID: <1248177758.9635@email.mot.com> chzwtv From orchardman at murash.com Tue Jul 21 16:34:43 2009 From: orchardman at murash.com (Brennen Liesch) Date: Tue, 21 Jul 2009 17:34:43 +0100 Subject: gunship Message-ID: <2613BBFB15720DD510213E9D7E321AC113960E@murash.com> Fmenale Orgasm Revealed - Learn the Secrets.www[dot]med95[dot]net From roland at redhat.com Tue Jul 21 20:58:01 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 21 Jul 2009 13:58:01 -0700 (PDT) Subject: Q: utrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Monday, 20 July 2009 19:22:40 +0200 <20090720172240.GA22459@redhat.com> References: <20090720172240.GA22459@redhat.com> Message-ID: <20090721205801.9FDDA64@magilla.sf.frob.com> > First of all, I believe ptrace_check_attach() is buggy. Yup, sure is! As I mentioned before, utrace-ptrace.patch is a source of couple of ideas, but I don't think you should take it as a "first draft" to work on and fix. Just attack implementing ptrace fresh in light of all the ptrace cleanup work you've been doing and other issues we've been talking about. > For example, utrace_control(UTRACE_STOP)->utrace_do_stop() finds > the child inside utrace_report_jctl() path in TASK_STOPPED state, Where? utrace_report_jctl is called with the siglock held, and resets to TASK_RUNNING before it unlocks. > sets utrace->stopped and returns true. After that utrace_report_jctl() > clears ->stopped and another engine's ->report_jctl does mutex_lock() > and sets ->state == TASK_INTERRUPTIBLE. TASK_STOPPED should never be seen (by someone holding the siglock, like utrace_do_stop does) until after all ->report_jctl hooks have finished. Thanks, Roland From roland at redhat.com Tue Jul 21 23:15:02 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 21 Jul 2009 16:15:02 -0700 (PDT) Subject: Q: utrace_stop() && notification In-Reply-To: Oleg Nesterov's message of Monday, 20 July 2009 17:26:52 +0200 <20090720152652.GA17395@redhat.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> Message-ID: <20090721231502.849956D036@magilla.sf.frob.com> > The usage of ->ptrace in utrace-ptrace is racy [...] Sure. Replace it. I'm not sure what purpose ->ptrace (or ctx->flags) serves for attach/detach. You need somewhere to store the PTRACE_SETOPTIONS state and so forth, sure. But you can probably just handle the attachedness at the utrace level. That's what UTRACE_ATTACH_EXCLUSIVE is for. > I think we need another variable which should be used instead, and > the only "good" place where it can live is engine->data, it should > point to "struct ptrace_xxx". Of course! That was the main point of the whole ptrace-tracee data structure cleanup. > Yes, I see. That is why I named it "notify_stopped", not report_xxx, > to emphasize it is really special and should be used with care and only > when really needed. Right, I got that. > So, if we do not want to add the special (and not-a-report) hooks > into engine->ops, then perhaps it makes sense to do [...] That is exactly the kludge the bad old utrace-ptrace.patch does. > So, perhaps we can just add engine->ops->notify_stopped() (or even [...] My main point was that we should look for an entirely different way to attack the problem. If I thought this hook would only be used for ptrace, it might be fine. (OTOH then it's not all that much better than the terrible ptrace-only kludge.) But AFAICT we'd likely wind up with every other new utrace module that cares about doing synchronization with debugger threads needing to use this hook too. That's why I want to talk about the general case in the utrace API, and not just ptrace. Let's ignore SIGCHLD for a moment, and just think about ptrace's report_* waking up wait. That is like what we expect will be the general case of this: a debugger thread wants to sleep somehow and have its report_* callbacks say "wake the debugger so it can examine me". So, how does the utrace module writer build that? You'd probably use wait_event() et al in your debugger thread, and wake_up() in report_* callbacks. (That's approximately what you have in ptrace+wait.) So how much is satisfied with a "delayed wake-up" (rather than an open-ended hook). Let's say: utrace_wake_up(task, engine, wqh); // replaces wake_up(wqh); return UTRACE_STOP; // | UTRACE_SIGNAL_IGN|UTRACE_SIGNAL_HOLD That would mean, approximately, as if wake_up(wqh) and then the wakee had called utrace_barrier(task,engine), but without the sched flutter. Formally, I think the guarantee should be "when utrace_barrier would return for you". Technically this means that if your callback did not use UTRACE_STOP, it's just sometime after your callback returns. But if you did use UTRACE_STOP, then it means after the task will definitely stop. That's all it means today, but I think we want to strengthen that guarantee so that when you have used UTRACE_STOP (either in a callback already in progress when you called utrace_barrier, or in a utrace_control call before the utrace_barrier call), utrace_barrier doesn't return until "utrace_prepare_examine will work", i.e. actually in TASK_TRACED/STOPPED. In ptrace, I think this alone might suffice to cover things "cleanly" in the utrace API. (That is, clean for utrace. ;-) The ptrace layer could use the trick of a custom wake function to implement SIGCHLD without needing anything but utrace_wake_up from the utrace layer. That is at base the same thing as your notify_stopped hook--ptrace will supply a hook that runs in very special circumstances. But for the more common case in other modules, using utrace_wake_up/wait_event this way can be very straightforward and foolproof. Thoughts? Thanks, Roland From oleg at redhat.com Wed Jul 22 16:13:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 22 Jul 2009 18:13:31 +0200 Subject: Q: utrace && ptrace_check_attach() In-Reply-To: <20090721205801.9FDDA64@magilla.sf.frob.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> Message-ID: <20090722161331.GA7305@redhat.com> On 07/21, Roland McGrath wrote: > > > For example, utrace_control(UTRACE_STOP)->utrace_do_stop() finds > > the child inside utrace_report_jctl() path in TASK_STOPPED state, > > Where? utrace_report_jctl is called with the siglock held, and resets > to TASK_RUNNING before it unlocks. > > > sets utrace->stopped and returns true. After that utrace_report_jctl() > > clears ->stopped and another engine's ->report_jctl does mutex_lock() > > and sets ->state == TASK_INTERRUPTIBLE. > > TASK_STOPPED should never be seen (by someone holding the siglock, like > utrace_do_stop does) until after all ->report_jctl hooks have finished. Well yes, this particular scenario is not possible, but... OK, please forget about this for the moment. Why utrace_report_jctl() and utrace_get_signal() have to clear ->stopped ? Because unlike utrace_stop(), do_signal_stop() does not do finish_utrace_stop(). This means that utrace_report_jctl() and utrace_get_signal() might be called with ->stopped == true, ->stopped can be set by UTRACE_STOP/UTRACE_DETACH while we were stopped _before_. (btw, I think the comment in utrace_report_jctl() above "->stopped = 0" is confusing, it looks as if we are trying to prevent the race with utrace_do_stop() which was called after the caller sets TASK_STOPPED). Now return to the problem. It is even simpler (and worse) than I thought. Let's suppose the tracee is TASK_STOPPED, and the tracer does ptrace_check_attach(). utrace_control(UTRACE_STOP) sets ->stopped = true. But, the tracee is still TASK_STOPPED, not TASK_TRACED, SIGCONT can wake it up ? This means ptrace_check_attach() can succeed but the tracee can even return to the user-space after that, no? There is no guarantee utrace_get_signal() will call finish_resume_report(). For example, if there are no pending signals, we just clear ->stopped and return after dequeue_signal(). Oh, I hope I missed something. Oleg. From info at soft-direct.net Wed Jul 22 16:36:24 2009 From: info at soft-direct.net (Florence de Fizeo) Date: Wed, 22 Jul 2009 19:36:24 +0300 Subject: =?utf-8?q?Votre_devis_Standard_t=C3=A9l=C3=A9phonique?= Message-ID: <0c406c2a5656c228d33397c4c19e5992@om2.market-products.com> An HTML attachment was scrubbed... URL: From mldireto at tudoemoferta.com.br Wed Jul 22 16:12:52 2009 From: mldireto at tudoemoferta.com.br (Englobe Sistemas e E-commerce) Date: Wed, 22 Jul 2009 13:12:52 -0300 Subject: Estamos a procura de empreendedores Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Jul 22 18:03:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 22 Jul 2009 20:03:51 +0200 Subject: Q: utrace_stop() && notification In-Reply-To: <20090721231502.849956D036@magilla.sf.frob.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> Message-ID: <20090722180351.GB7305@redhat.com> On 07/21, Roland McGrath wrote: > > > So, if we do not want to add the special (and not-a-report) hooks > > into engine->ops, then perhaps it makes sense to do > [...] > > That is exactly the kludge I fully agree with the "kludge" above. > > So, perhaps we can just add engine->ops->notify_stopped() (or even [...] > > My main point was that we should look for an entirely different way to > attack the problem. If I thought this hook would only be used for > ptrace, it might be fine. (OTOH then it's not all that much better than > the terrible ptrace-only kludge.) But AFAICT we'd likely wind up with > every other new utrace module that cares about doing synchronization > with debugger threads needing to use this hook too. That's why I want > to talk about the general case in the utrace API, and not just ptrace. Yes sure. That is why I tried to talk about utrace notifications "in general", not only about ptrace case. > Let's ignore SIGCHLD for a moment, and just think about ptrace's > report_* waking up wait. That is like what we expect will be the > general case of this: a debugger thread wants to sleep somehow and have > its report_* callbacks say "wake the debugger so it can examine me". > > So, how does the utrace module writer build that? You'd probably use > wait_event() et al in your debugger thread, and wake_up() in report_* > callbacks. OK. > (That's approximately what you have in ptrace+wait.) Hmm. Except in this case ptracer can be running. It is not placed on any wqh, but still needs a notification. > So how much is satisfied with a "delayed wake-up" (rather than an > open-ended hook). Let's say: > > utrace_wake_up(task, engine, wqh); // replaces wake_up(wqh); > return UTRACE_STOP; // | UTRACE_SIGNAL_IGN|UTRACE_SIGNAL_HOLD > > That would mean, approximately, as if wake_up(wqh) and then the wakee > had called utrace_barrier(task,engine), but without the sched flutter. > > Formally, I think the guarantee should be "when utrace_barrier would > return for you". Technically this means that if your callback did not > use UTRACE_STOP, it's just sometime after your callback returns. But if > you did use UTRACE_STOP, then it means after the task will definitely > stop. This looks nice, but > That's all it means today, but I think we want to strengthen that > guarantee so that when you have used UTRACE_STOP (either in a callback > already in progress when you called utrace_barrier, or in a utrace_control > call before the utrace_barrier call), utrace_barrier doesn't return until > "utrace_prepare_examine will work", i.e. actually in TASK_TRACED/STOPPED. this means the meaning of utrace_barrier() should be changed? > In ptrace, I think this alone might suffice to cover things "cleanly" in > the utrace API. (That is, clean for utrace. ;-) The ptrace layer could > use the trick of a custom wake function to implement SIGCHLD A custom wake function can only be used if the wakee has already called add_wait_queue(). Wake function belongs to wait_queue_t, not to wait_queue_head_t. But this doesn't really matter. I think that using wait_queue_func_t->func() (or whatever else we use to implement the utrace-delayed-wakeup) to do ptrace-specific hacks is not better than engine->ops->special_hook(). In essence, this looks like we add another ->ops into engine implicitly. > without > needing anything but utrace_wake_up from the utrace layer. Not sure I understand how to implement this all :( Oleg. From oleg at redhat.com Wed Jul 22 18:25:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 22 Jul 2009 20:25:17 +0200 Subject: Q: utrace_stop() && notification In-Reply-To: <20090721231502.849956D036@magilla.sf.frob.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> Message-ID: <20090722182517.GC7305@redhat.com> (change subject) On 07/21, Roland McGrath wrote: > > > The usage of ->ptrace in utrace-ptrace is racy [...] > > Sure. Replace it. I'm not sure what purpose ->ptrace (or ctx->flags) > serves for attach/detach. You need somewhere to store the > PTRACE_SETOPTIONS state and so forth, sure. But you can probably just > handle the attachedness at the utrace level. That's what > UTRACE_ATTACH_EXCLUSIVE is for. Yes. As for ->ptrace, I think it should die. The only problem is PT_PTRACED bit. It would be nice to move it into ->utrace_flags, but this needs some not-very-nice changes. > > I think we need another variable which should be used instead, and > > the only "good" place where it can live is engine->data, it should > > point to "struct ptrace_xxx". > > Of course! That was the main point of the whole ptrace-tracee data > structure cleanup. Yes, yes, I see. But there is a problem. Which I didn't expect at all. Who will kfree() engine->data ? sys_ptrace(PTRACE_DETACH) can do this. But what if the tracer exits and detaches? Or release_task() does untrace. Yes, we can use task_struct->ptrace_ctx which is freed by free_task(), in this case engine->data == child->ptrace_ctx. But imho this would be very bad. OTOH, perhaps we can't avoid task_struct->ptrace_ctx. Otherwise, it is not easy to move task_struct->parent into ptrace_context. Oleg. From oleg at redhat.com Wed Jul 22 18:29:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 22 Jul 2009 20:29:41 +0200 Subject: engine->data && ptrace_context In-Reply-To: <20090722182517.GC7305@redhat.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> Message-ID: <20090722182941.GD7305@redhat.com> On 07/22, Oleg Nesterov wrote: > > (change subject) (really change the subject) On 07/21, Roland McGrath wrote: > > > The usage of ->ptrace in utrace-ptrace is racy [...] > > Sure. Replace it. I'm not sure what purpose ->ptrace (or ctx->flags) > serves for attach/detach. You need somewhere to store the > PTRACE_SETOPTIONS state and so forth, sure. But you can probably just > handle the attachedness at the utrace level. That's what > UTRACE_ATTACH_EXCLUSIVE is for. Yes. As for ->ptrace, I think it should die. The only problem is PT_PTRACED bit. It would be nice to move it into ->utrace_flags, but this needs some not-very-nice changes. > > I think we need another variable which should be used instead, and > > the only "good" place where it can live is engine->data, it should > > point to "struct ptrace_xxx". > > Of course! That was the main point of the whole ptrace-tracee data > structure cleanup. Yes, yes, I see. But there is a problem. Which I didn't expect at all. Who will kfree() engine->data ? sys_ptrace(PTRACE_DETACH) can do this. But what if the tracer exits and detaches? Or release_task() does untrace. Yes, we can use task_struct->ptrace_ctx which is freed by free_task(), in this case engine->data == child->ptrace_ctx. But imho this would be very bad. OTOH, perhaps we can't avoid task_struct->ptrace_ctx. Otherwise, it is not easy to move task_struct->parent into ptrace_context. Oleg. From oleg at redhat.com Wed Jul 22 19:43:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 22 Jul 2009 21:43:00 +0200 Subject: Q: utrace_prepare_examine() && get_task_struct(target) In-Reply-To: <20090721030037.A6A7B6D02E@magilla.sf.frob.com> References: <20090720193836.GA7350@redhat.com> <20090721030037.A6A7B6D02E@magilla.sf.frob.com> Message-ID: <20090722194300.GE7305@redhat.com> On 07/20, Roland McGrath wrote: > > Yeah, it might just need this: > > diff --git a/kernel/utrace.c b/kernel/utrace.c > index 74b5fc5..60af805 100644 > --- a/kernel/utrace.c > +++ b/kernel/utrace.c > @@ -549,6 +549,7 @@ restart: > list_for_each_entry_safe(engine, next, &utrace->attached, entry) { > ops = engine->ops; > engine->ops = NULL; > + engine->flags = 0; > list_move(&engine->entry, &detached); I think this makes sense regardless. > put_detached_list(&detached); > + > + /* > + * Make sure all engine->flags and engine->ops updates are done > + * before the current task_struct might really die. > + */ > + smp_wmb(); I don't think we need additional barriers here or in prepare/finish, rcu_call() should play correctly with rcu_read_lock(). IOW, rcu_read_lock() must have enough "barrierness" wrt rcu_call(). > Let me explain the general notion. It's always been a little iffy, and it > definitely deserves an airing now in your fresh review of all things utrace. > > The root of the thing is that modules can't use get_task_struct(). Aaaah. > The other calls use get_utrace_lock to implement this guarantee. It checks > that your engine is attached before it looks at the task_struct, and this > is (supposedly) synchronized with detach and reap safely. (You should be > checking on that supposition, Oleg. ;-) I still think EXIT_DEAD check must die ;) > For a direct poke at task->thread.something you can make it work. > > rcu_read_lock(); > ret = utrace_prepare_examine(task, engine, &exam); > if (ret) goto hell; > fiddle = task->faddle; > rcu_read_unlock(); > ret = utrace_finish_examine(task, engine, &exam); > if (ret) goto hell; > > Even though utrace_prepare_examine (wait_task_inactive) will block and > that lets RCU stuff happen, when you've come back again you will be in > rcu_read_lock across the put_task_struct it does. So task is live until > rcu_read_unlock(). (I have no idea if intentionally allowing a block > inside rcu_read_lock freaks out lockdep or something.) Hmm. I think without CONFIG_PREEMPT_RCU schedule_debug() will complain if wait_task_inactive() blocks. In any case, without CONFIG_PREEMPT_RCU we must not schedule() under rcu_read_lock(), because rcuclassic considers schedule() call as "->passed_quiesc = true". > This suggests perhaps utrace_prepare_examine ought to keep a task ref to > be released by utrace_finish_examine. But then it's a back-door way for > modules to use get/put_task_struct and leak task_structs. Is that OK? Oh, don't ask me ;) But I think this is very natural. Yes, with this change the caller must always do utrace_finish_examine() if _prepare_ succeeds, but a buggy utrace module can leak memory or just crash the kernel in many ways. Or we can export __put_task_struct(), this means more work for utrace user. Or. Actually, when I started read utrace.c I was surprised there is no "task_struct *tracee" in "struct utrace_engine". Perhaps engine itself should ping task_struct ? And engine->tracee can be very handy. Oleg. From roland at redhat.com Thu Jul 23 00:21:12 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 22 Jul 2009 17:21:12 -0700 (PDT) Subject: Q: utrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Wednesday, 22 July 2009 18:13:31 +0200 <20090722161331.GA7305@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> Message-ID: <20090723002112.6DCE5280@magilla.sf.frob.com> > Why utrace_report_jctl() and utrace_get_signal() have to clear ->stopped? > Because unlike utrace_stop(), do_signal_stop() does not do > finish_utrace_stop(). Correct. > This means that utrace_report_jctl() and utrace_get_signal() might be > called with ->stopped == true, ->stopped can be set by > UTRACE_STOP/UTRACE_DETACH while we were stopped _before_. By utrace_do_stop(), correct. > (btw, I think the comment in utrace_report_jctl() above "->stopped = 0" > is confusing, it looks as if we are trying to prevent the race with > utrace_do_stop() which was called after the caller sets TASK_STOPPED). I am a bit confused now too. Please rewrite any comments to be more clear as you come across them. > Now return to the problem. It is even simpler (and worse) than I thought. > Let's suppose the tracee is TASK_STOPPED, and the tracer does > ptrace_check_attach(). utrace_control(UTRACE_STOP) sets ->stopped = true. > But, the tracee is still TASK_STOPPED, not TASK_TRACED, SIGCONT can wake > it up ? Correct. It will always then go through utrace_get_signal(), which is supposed to be responsible for handling that case. > This means ptrace_check_attach() can succeed but the tracee can even return > to the user-space after that, no? There is no guarantee utrace_get_signal() > will call finish_resume_report(). For example, if there are no pending > signals, we just clear ->stopped and return after dequeue_signal(). Yes, I think you're right. I think the "if (unlikely(utrace->stopped)) {" case in utrace_get_signal() needs to do some variant of utrace_reset. If any engine_wants_stop() then it should not dequeue a signal even if one is ready, and probably it should also not do any spontaneous report. OTOH perhaps it should do a spontaneous report in that case, so that if you used utrace_control(,,UTRACE_STOP) while in TASK_STOPPED, you get a UTRACE_SIGNAL_REPORT callback at SIGCONT time. If that's the plan, then all we need is utrace_do_stop()'s task_is_stopped() case to set ->report too (and set_notify_resume for the invariant, though it's superfluous really). Thanks, Roland From confirm-s2-ypucv5xfcozqj1cyuhi2ppggzgmy1sqd-utrace-devel=redhat.com at yahoogrupos.com.br Thu Jul 23 01:00:02 2009 From: confirm-s2-ypucv5xfcozqj1cyuhi2ppggzgmy1sqd-utrace-devel=redhat.com at yahoogrupos.com.br (Yahoo! Grupos) Date: 23 Jul 2009 01:00:02 -0000 Subject: Confirma =?iso-8859-1?q?=E7=E3?= o de pedido para entrar no grupo de_amigo_para_amigo Message-ID: <1248310802.41.74155.w3@yahoogrupos.com.br> Ol? utrace-devel at redhat.com, Recebemos sua solicita??o para entrar no grupo de_amigo_para_amigo do Yahoo! Grupos, um servi?o de comunidades online gratuito e super f?cil de usar. Este pedido expirar? em 7 dias. PARA ENTRAR NESTE GRUPO: 1) V? para o site do Yahoo! Grupos clicando neste link: http://br.groups.yahoo.com/i?i=ypucv5xfcozqj1cyuhi2ppggzgmy1sqd&e=utrace-devel%40redhat%2Ecom (Se n?o funcionar, use os comandos para cortar e colar o link acima na barra de endere?o do seu navegador.) -OU- 2) RESPONDA a este e-mail clicando em "Responder" e depois em "Enviar", no seu programa de e-mail. Se voc? n?o fez esta solicita??o ou se n?o tem interesse em entrar no grupo de_amigo_para_amigo, por favor, ignore esta mensagem. Sauda??es, Atendimento ao usu?rio do Yahoo! Grupos O uso que voc? faz do Yahoo! Grupos est? sujeito aos http://br.yahoo.com/info/utos.html From roland at redhat.com Thu Jul 23 01:02:24 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 22 Jul 2009 18:02:24 -0700 (PDT) Subject: Q: utrace_stop() && notification In-Reply-To: Oleg Nesterov's message of Wednesday, 22 July 2009 20:03:51 +0200 <20090722180351.GB7305@redhat.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722180351.GB7305@redhat.com> Message-ID: <20090723010224.638022D36@magilla.sf.frob.com> > I fully agree with the "kludge" above. :-) > Yes sure. That is why I tried to talk about utrace notifications > "in general", not only about ptrace case. Ok, good. I saw only ptrace-specific things in that post so I wanted to be clear. > > So, how does the utrace module writer build that? You'd probably use > > wait_event() et al in your debugger thread, and wake_up() in report_* > > callbacks. > > OK. Is there anything else it might likely be? > Hmm. Except in this case ptracer can be running. It is not placed > on any wqh, but still needs a notification. Right. I remembered that having coffee this morning. Anyway, I really meant this to be the general-case discussion about utrace API features first and consider exact ptrace details a bit later. > > So how much is satisfied with a "delayed wake-up" (rather than an > > open-ended hook). Let's say: > > > > utrace_wake_up(task, engine, wqh); // replaces wake_up(wqh); > > return UTRACE_STOP; // | UTRACE_SIGNAL_IGN|UTRACE_SIGNAL_HOLD > > > > That would mean, approximately, as if wake_up(wqh) and then the wakee > > had called utrace_barrier(task,engine), but without the sched flutter. > > > > Formally, I think the guarantee should be "when utrace_barrier would > > return for you". Technically this means that if your callback did not > > use UTRACE_STOP, it's just sometime after your callback returns. But if > > you did use UTRACE_STOP, then it means after the task will definitely > > stop. > > This looks nice, but > > > That's all it means today, but I think we want to strengthen that > > guarantee so that when you have used UTRACE_STOP (either in a callback > > already in progress when you called utrace_barrier, or in a utrace_control > > call before the utrace_barrier call), utrace_barrier doesn't return until > > "utrace_prepare_examine will work", i.e. actually in TASK_TRACED/STOPPED. > > this means the meaning of utrace_barrier() should be changed? Right, there would be a new guarantee for utrace_barrier when you've used UTRACE_STOP on your engine. > A custom wake function can only be used if the wakee has already called > add_wait_queue(). Wake function belongs to wait_queue_t, not to > wait_queue_head_t. Yes, I know. > But this doesn't really matter. I think that using wait_queue_func_t->func() > (or whatever else we use to implement the utrace-delayed-wakeup) to do > ptrace-specific hacks is not better than engine->ops->special_hook(). > > In essence, this looks like we add another ->ops into engine implicitly. > > without > > needing anything but utrace_wake_up from the utrace layer. > > Not sure I understand how to implement this all :( You mean how to implement this utrace API inside utrace.c? That's OK for the moment. I meant to have us think through the API from the perspective of utrace module-writers (including ptrace) and reach a fairly firm idea of what API we'll be happy with before dealing with implementing it. I think it will be fairly straightforward along with some cleanups inside utrace that we wanted to consider anyway. Thanks, Roland From roland at redhat.com Thu Jul 23 01:23:25 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 22 Jul 2009 18:23:25 -0700 (PDT) Subject: engine->data && ptrace_context In-Reply-To: Oleg Nesterov's message of Wednesday, 22 July 2009 20:29:41 +0200 <20090722182941.GD7305@redhat.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> Message-ID: <20090723012325.903F62D36@magilla.sf.frob.com> > > serves for attach/detach. You need somewhere to store the > > PTRACE_SETOPTIONS state and so forth, sure. But you can probably just > > handle the attachedness at the utrace level. That's what > > UTRACE_ATTACH_EXCLUSIVE is for. > > Yes. As for ->ptrace, I think it should die. The only problem is > PT_PTRACED bit. It would be nice to move it into ->utrace_flags, but > this needs some not-very-nice changes. What is PT_PTRACED good for? Why do you need it at all? That's what my quoted paragraph above is saying: you don't. The "is someone already ptrace'ing it" bit is determined by UTRACE_ATTACH_MATCH_OPS, &ptrace_ops. Or perhaps race issues will make you want to have it possible an engine is attached momentarily when ptrace_context is is not set up yet or is being torn down. In that case, ctx->tracer == NULL or something probably works. > But there is a problem. Which I didn't expect at all. > > Who will kfree() engine->data ? > > sys_ptrace(PTRACE_DETACH) can do this. But what if the tracer exits > and detaches? Or release_task() does untrace. All of these are some ptrace.c path that has to use UTRACE_DETACH, or else is where your ptrace_ops.report_reap hook would be called. Whoever does a successful UTRACE_DETACH should free it. So that can be after a utrace_control call that returned 0 (or utrace_barrier after), or in a callback that will return UTRACE_DETACH, or in a report_reap callback. > Yes, we can use task_struct->ptrace_ctx which is freed by free_task(), > in this case engine->data == child->ptrace_ctx. But imho this would > be very bad. Agreed, we should get rid of that pointer in task_struct entirely. > OTOH, perhaps we can't avoid task_struct->ptrace_ctx. Otherwise, > it is not easy to move task_struct->parent into ptrace_context. Well, that's a different can of worms. We should look at each case of anything outside {compat_,}sys_ptrace itself and ptrace's utrace callbacks that needs to look at that pointer and figure out how to rework things. Thanks, Roland From roland at redhat.com Thu Jul 23 02:41:52 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 22 Jul 2009 19:41:52 -0700 (PDT) Subject: Q: utrace_prepare_examine() && get_task_struct(target) In-Reply-To: Oleg Nesterov's message of Wednesday, 22 July 2009 21:43:00 +0200 <20090722194300.GE7305@redhat.com> References: <20090720193836.GA7350@redhat.com> <20090721030037.A6A7B6D02E@magilla.sf.frob.com> <20090722194300.GE7305@redhat.com> Message-ID: <20090723024152.D9432280@magilla.sf.frob.com> > > engine->ops = NULL; > > + engine->flags = 0; > > list_move(&engine->entry, &detached); > > I think this makes sense regardless. Agreed. > > + * Make sure all engine->flags and engine->ops updates are done > > + * before the current task_struct might really die. > > + */ > > + smp_wmb(); > > I don't think we need additional barriers here or in prepare/finish, > rcu_call() should play correctly with rcu_read_lock(). > > IOW, rcu_read_lock() must have enough "barrierness" wrt rcu_call(). Right, OK. > > The other calls use get_utrace_lock to implement this guarantee. It checks > > that your engine is attached before it looks at the task_struct, and this > > is (supposedly) synchronized with detach and reap safely. (You should be > > checking on that supposition, Oleg. ;-) > > I still think EXIT_DEAD check must die ;) In get_utrace_lock, you mean? Do you mean it's superfluous because we can rely on utrace_reap having cleared engine->ops before it matters to us? > Hmm. I think without CONFIG_PREEMPT_RCU schedule_debug() will complain > if wait_task_inactive() blocks. Ok, I thought something like that might be true. > In any case, without CONFIG_PREEMPT_RCU we must not schedule() under > rcu_read_lock(), because rcuclassic considers schedule() call as > "->passed_quiesc = true". That's exactly what I meant by "lets RCU stuff happen". But I was supposing it would work because after you come out of schedule() it's as if you'd done rcu_read_unlock();rcu_read_lock(); before put_task_struct(). But anyway, I was just illustrating what might be the very best you can do with what we have now, to say that it is clearly inadequate. > > This suggests perhaps utrace_prepare_examine ought to keep a task ref to > > be released by utrace_finish_examine. But then it's a back-door way for > > modules to use get/put_task_struct and leak task_structs. Is that OK? > > Oh, don't ask me ;) Well, I was hoping we might get some other people into the discussion too. > But I think this is very natural. Yes, with this change the caller must > always do utrace_finish_examine() if _prepare_ succeeds, but a buggy > utrace module can leak memory or just crash the kernel in many ways. Sure. Of course it can do get_task_struct() today, and just is guaranteed to leak since it can't do put_task_struct(). > Or we can export __put_task_struct(), this means more work for utrace > user. Right, we should be finding the utrace API that makes it easiest for users to get things right, that's primary. I was just concerned that upstream folks might say that modules can't do put_task_struct() and that's how they want it, and that being so they don't want a backdoor method to do get_task_struct()/put_task_struct() either because whatever bad modules they are worried about would exploit it. > Or. Actually, when I started read utrace.c I was surprised there is > no "task_struct *tracee" in "struct utrace_engine". Perhaps engine > itself should ping task_struct ? And engine->tracee can be very handy. I don't think a detached struct utrace_engine should pin any task_struct. That just makes utrace_engine_{get,put} a proxy for {get,put}_task_struct. And if it doesn't, then it's not much different from what we have now, is it? That is, given unpredictable asynchronous detach because of SIGKILL or mt-exec + parent wait or self-reaping. Perhaps I'm wrong to want to avoid keeping task_struct refs like that. I'm open to opinions. There are other API reasons that I never wanted a task_struct pointer in struct utrace_engine. But we can get into those later. It's moot if we concur with my idea that holding task_struct refs past detach is bad. Thanks, Roland From indoxyl at teknotur.com Thu Jul 23 05:30:09 2009 From: indoxyl at teknotur.com (indoxyl) Date: Thu, 23 Jul 2009 05:30:09 -0000 Subject: twinges Message-ID: <20090723052740.827914conniving@teknotur.com> 3 Femlae Orgasm Friendly Posittions Part II.www.mu77(.net) From fche at elastic.org Thu Jul 23 11:41:19 2009 From: fche at elastic.org (Frank Ch. Eigler) Date: Thu, 23 Jul 2009 07:41:19 -0400 Subject: Forw: [ananth@in.ibm.com: Q: attaching engines to all threads] Message-ID: <20090723114119.GD28619@elastic.org> Hi - Forwarded from ananth, whose emails are not hitting utrace-devel for some reason: Date: Wed, 22 Jul 2009 13:21:43 +0530 From: Ananth N Mavinakayanahalli To: utrace-devel at redhat.com Subject: Q: attaching engines to all threads Roland, Oleg, What do you think is the best model to attach engines to all threads of a process safely using utrace? Uprobes implements it in a slightly convoluted fashion, while I wrote (assuming 'task' is a valid task_struct, corresponding to the tgid of the multi-threaded process): + rcu_read_lock(); + do { + get_task_struct(t); + rcu_read_unlock(); + ret = (t); + if (ret && (ret != EINPROGRESS)) + goto err; + rcu_read_lock(); + put_task_struct(t); + ret = 0; + t = next_thread(t); + } while (t != task); + + rcu_read_unlock(); But this is still not 'safe' as there are still races/possibility of t dying within the unlock/lock in the loop. And its not possible to hold the rcu_read_lock all the way since the routine that attaches the engine will need to do a kzalloc and the like for housekeeping. What is your preferred approach for this? Ananth PS: I believe getting a feature/callback implemented in utrace so not every user of the infrastructure needs to reinvent the wheel is a good idea. In fact, it may be a better thing to have simply to avoid buggy implementations. From oleg at redhat.com Thu Jul 23 19:02:34 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 23 Jul 2009 21:02:34 +0200 Subject: engine->data && ptrace_context In-Reply-To: <20090723012325.903F62D36@magilla.sf.frob.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> Message-ID: <20090723190234.GA12037@redhat.com> On 07/22, Roland McGrath wrote: > > > > serves for attach/detach. You need somewhere to store the > > > PTRACE_SETOPTIONS state and so forth, sure. But you can probably just > > > handle the attachedness at the utrace level. That's what > > > UTRACE_ATTACH_EXCLUSIVE is for. > > > > Yes. As for ->ptrace, I think it should die. The only problem is > > PT_PTRACED bit. It would be nice to move it into ->utrace_flags, but > > this needs some not-very-nice changes. > > What is PT_PTRACED good for? Why do you need it at all? For example, wait_consider_task(). Even some tracehooks, say, tracehook_notify_death() need task_is_ptraced(). If we kill (we should) ->ptrace, how can we check whether the task is ptraced? We can't check utrace_attach_task(p, MATCH_OPS, ptrace_ops) != NULL, this needs utrace->lock. I think we need a flag in ->utrace_flags, or just ptrace_attached:1 in struct utrace. > > Who will kfree() engine->data ? > > > > sys_ptrace(PTRACE_DETACH) can do this. But what if the tracer exits > > and detaches? Or release_task() does untrace. > > All of these are some ptrace.c path that has to use UTRACE_DETACH, > or else is where your ptrace_ops.report_reap hook would be called. > Whoever does a successful UTRACE_DETACH should free it. So that can be > after a utrace_control call that returned 0 (or utrace_barrier after), > or in a callback that will return UTRACE_DETACH, or in a report_reap > callback. Hmm. Yes, looks like you are right... Not sure what I was worried about. I did have some concerns, but I guess I was wrong. Good! > > OTOH, perhaps we can't avoid task_struct->ptrace_ctx. Otherwise, > > it is not easy to move task_struct->parent into ptrace_context. > > Well, that's a different can of worms. We should look at each case of > anything outside {compat_,}sys_ptrace itself and ptrace's utrace callbacks > that needs to look at that pointer and figure out how to rework things. Yes. Oleg. From oleg at redhat.com Thu Jul 23 19:34:14 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 23 Jul 2009 21:34:14 +0200 Subject: Q: utrace && ptrace_check_attach() In-Reply-To: <20090723002112.6DCE5280@magilla.sf.frob.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> Message-ID: <20090723193414.GB12037@redhat.com> On 07/22, Roland McGrath wrote: > > > This means ptrace_check_attach() can succeed but the tracee can even return > > to the user-space after that, no? There is no guarantee utrace_get_signal() > > will call finish_resume_report(). For example, if there are no pending > > signals, we just clear ->stopped and return after dequeue_signal(). > > Yes, I think you're right. I think the "if (unlikely(utrace->stopped)) {" > case in utrace_get_signal() needs to do some variant of utrace_reset. If > any engine_wants_stop() then it should not dequeue a signal even if one is > ready, and probably it should also not do any spontaneous report. Hmm. If ->stopped == T after return from do_signal_stop()->schedule(), then we must have the engine which is engine_wants_stop(), no? > OTOH perhaps it should do a spontaneous report in that case, so that if you > used utrace_control(,,UTRACE_STOP) while in TASK_STOPPED, you get a > UTRACE_SIGNAL_REPORT callback at SIGCONT time. If that's the plan, then > all we need is utrace_do_stop()'s task_is_stopped() case to set ->report > too (and set_notify_resume for the invariant, though it's superfluous really). Damn. Just can't think today... Roland, can we just remove all code which plays with ->stopped in utrace_report_jctl() and utrace_get_signal(), and do something like --- kernel/utrace.c +++ kernel/utrace.c @@ -390,6 +390,13 @@ static bool utrace_stop(struct task_stru * for stop signals and SIGCONT. */ spin_lock(&utrace->lock); + + return utrace_stop_locked(task, utrace, report); +} + +bool utrace_stop_locked(struct task_struct *task, struct utrace *utrace, + bool report) +{ spin_lock_irq(&task->sighand->siglock); if (unlikely(sigismember(&task->pending.signal, SIGKILL))) { --- kernel/signal.c +++ kernel/signal.c @@ -1602,6 +1602,16 @@ static int do_signal_stop(int signr) do { schedule(); } while (try_to_freeze()); + + // needs a tracehook helper + if (utrace->stopped) { + spin_lock(&utrace->lock); + if (utrace->stopped) + utrace_stop_locked(); + else + spin_unlock(&utrace->lock); + } + /* * Now we don't run again until continued. */ No? Oleg. From oleg at redhat.com Thu Jul 23 21:06:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 23 Jul 2009 23:06:09 +0200 Subject: Q: utrace_prepare_examine() && get_task_struct(target) In-Reply-To: <20090723024152.D9432280@magilla.sf.frob.com> References: <20090720193836.GA7350@redhat.com> <20090721030037.A6A7B6D02E@magilla.sf.frob.com> <20090722194300.GE7305@redhat.com> <20090723024152.D9432280@magilla.sf.frob.com> Message-ID: <20090723210608.GC12037@redhat.com> On 07/22, Roland McGrath wrote: > > > I still think EXIT_DEAD check must die ;) > > In get_utrace_lock, you mean? Do you mean it's superfluous because we can > rely on utrace_reap having cleared engine->ops before it matters to us? Yes. Perhaps I missed something, but this check buys nothing. First of all this check is racy without tasklist. Bit it is also unneeded, I think. > > Or. Actually, when I started read utrace.c I was surprised there is > > no "task_struct *tracee" in "struct utrace_engine". Perhaps engine > > itself should ping task_struct ? And engine->tracee can be very handy. > > I don't think a detached struct utrace_engine should pin any task_struct. > That just makes utrace_engine_{get,put} a proxy for {get,put}_task_struct. Yes, > And if it doesn't, then it's not much different from what we have now, is > it? OK, agreed. Perhaps engine->tracee still makes sense even if engine doesn't pin task_struct, utrace_control/barrier/set_events do not need "target" argument in this case. And this means it would a bit be easier to use them. And we can kill _pid() helpers. But this is another story. Oleg. From newsletter at usbportugal.com Thu Jul 23 22:26:41 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Fri, 24 Jul 2009 00:26:41 +0200 Subject: =?iso-8859-1?q?J=E1_n=E3o_h=E1_mem=F3ria_de=2E=2E=2ESemana_30?= Message-ID: <294c09566021c5b3f54a8ee551cb19e2@newsletter2.usbportugal.com> An HTML attachment was scrubbed... URL: From concededly at pangallo.it Fri Jul 24 05:54:29 2009 From: concededly at pangallo.it (concededly) Date: Fri, 24 Jul 2009 05:54:29 -0000 Subject: reappeared Message-ID: <4A694B95_205214@pangallo.it> Know The Beest sexual Positions - Learn The Msitakes Most Guys Make.www.med84{.com} From divulgacao at visualrmc.com Fri Jul 24 12:46:24 2009 From: divulgacao at visualrmc.com (VISUAL RMC) Date: Fri, 24 Jul 2009 09:46:24 -0300 Subject: Tudo o que necessita !!! Message-ID: An HTML attachment was scrubbed... URL: From patrycja at sfc.pl Fri Jul 24 18:03:30 2009 From: patrycja at sfc.pl (Mortimer Day) Date: Fri, 24 Jul 2009 19:03:30 +0100 Subject: Get the young bull powers for doing her like a real macho. Message-ID: <20090724190330.9020905@sfc.pl> Doing your woman won't be a problem after hard and stressful day. http://duzrx.wrihkynqe.com/ From jongleur at uniset.com.tr Fri Jul 24 17:19:05 2009 From: jongleur at uniset.com.tr (jongleur) Date: Fri, 24 Jul 2009 17:19:05 +0000 Subject: adiaphorism Message-ID: The Sbecret Behind thhe Best Female Orgasms.www.wood96. com From roland at redhat.com Fri Jul 24 22:47:19 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 24 Jul 2009 15:47:19 -0700 (PDT) Subject: Q: utrace_prepare_examine() && get_task_struct(target) In-Reply-To: Oleg Nesterov's message of Thursday, 23 July 2009 23:06:09 +0200 <20090723210608.GC12037@redhat.com> References: <20090720193836.GA7350@redhat.com> <20090721030037.A6A7B6D02E@magilla.sf.frob.com> <20090722194300.GE7305@redhat.com> <20090723024152.D9432280@magilla.sf.frob.com> <20090723210608.GC12037@redhat.com> Message-ID: <20090724224719.5B53BE7EA@magilla.sf.frob.com> > > > I still think EXIT_DEAD check must die ;) > > > > In get_utrace_lock, you mean? Do you mean it's superfluous because we can > > rely on utrace_reap having cleared engine->ops before it matters to us? > > Yes. Perhaps I missed something, but this check buys nothing. First of > all this check is racy without tasklist. Bit it is also unneeded, I think. Good enough. Let's drop it. > Perhaps engine->tracee still makes sense even if engine doesn't pin > task_struct, utrace_control/barrier/set_events do not need "target" > argument in this case. And this means it would a bit be easier to > use them. And we can kill _pid() helpers. But this is another story. Yes, it's another story. I am inclined against it, but for reasons that are a bigger discussion. Thanks, Roland From roland at redhat.com Fri Jul 24 23:06:49 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 24 Jul 2009 16:06:49 -0700 (PDT) Subject: engine->data && ptrace_context In-Reply-To: Oleg Nesterov's message of Thursday, 23 July 2009 21:02:34 +0200 <20090723190234.GA12037@redhat.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> <20090723190234.GA12037@redhat.com> Message-ID: <20090724230649.8FD1C80563@magilla.sf.frob.com> > For example, wait_consider_task(). Even some tracehooks, say, > tracehook_notify_death() need task_is_ptraced(). Not "some", just that one, right? So these are all really the same one thing: ptrace interfering with normal parent wait/SIGCHLD. In previous iterations, we had tracehook_inhibit_wait for hiding this in the tracehook layer. Then I decided to drop that and wait to revisit it until the final big ptrace clean-up. And now here we are! In the first utrace API, we had a NOREAP feature for this "cleanly" in the utrace layer, so any engine could say it wanted to interfere like ptrace. That was only there for ptrace and we really want nothing else new ever to be able to interfere like that. (An engine could delay death by using UTRACE_STOP at exit-tracing, and can get reap notification to track what the real parent does, but it can't hide death from the real parent or prevent reaping once death is upon us.) I'm still fairly confident that it would not be a useful general feature to let anybody ever foul up the real parent like ptrace does. So bottom line, I think it is probably fine and proper to have some manner of ptrace-only special-case for this. For the core kernel code, I think it is probably right to reintroduce tracehook_inhibit_wait. do_wait_thread: if (!task_detached(p) && !tracehook_inhibit_wait(p)) { int ret = wait_consider_task(wo, tsk, 0, p); That keeps it simple and clean there. The logic inside tracehook_{inhibit_wait,notify_death,notify_jctl} will hide the actual implementation. I'm inclined to avoid any more magic bits in utrace_flags, because I expect those bits to become useful and precious later. So I'd do: static inline bool tracehook_inhibit_wait(struct task_struct *task) { return task->utrace_flags && utrace_inhibit_wait(task); } and then utrace_inhibit_wait can look at a bit we keep in struct utrace or something like that. I think we might be able to get away with unlocked checks of that bit in wait, if we're sure that we'll do an extra wake_up_parent after detach or whatnot. OTOH, here's another idea. I think it might be the case that after being ptrace-attached and before any place that could matter (i.e. entering an exit_state or TASK_STOPPED) the tracee will go through some ->report_* callback to ptrace. In synchronous callbacks, it can do current->flags|= and then we could use a PF_* flag for this and keep the tracehook_inhibit_wait check extremely cheap. Thanks, Roland From roland at redhat.com Sat Jul 25 00:19:33 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 24 Jul 2009 17:19:33 -0700 (PDT) Subject: Q: utrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Thursday, 23 July 2009 21:34:14 +0200 <20090723193414.GB12037@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> Message-ID: <20090725001933.861BEE7EA@magilla.sf.frob.com> > > Yes, I think you're right. I think the "if (unlikely(utrace->stopped)) {" > > case in utrace_get_signal() needs to do some variant of utrace_reset. If > > any engine_wants_stop() then it should not dequeue a signal even if one is > > ready, and probably it should also not do any spontaneous report. > > Hmm. If ->stopped == T after return from do_signal_stop()->schedule(), > then we must have the engine which is engine_wants_stop(), no? Hmm. If he went away, he would have done utrace_wakeup, so yes. > Damn. Just can't think today... I think you're doing better than I am. ;-) > Roland, can we just remove all code which plays with ->stopped in > utrace_report_jctl() and utrace_get_signal(), and do something like [...] > @@ -1602,6 +1602,16 @@ static int do_signal_stop(int signr) > do { > schedule(); > } while (try_to_freeze()); > + > + // needs a tracehook helper > + if (utrace->stopped) { Hmm. I guess we could. I think my original thinking was just minimizing the number of places in the core kernel code where we inserted any tracehook call, keeping them to about exactly where the ptrace hooks had been. But now I'd say it is certainly fine to insert another hook in the signals code if it keeps the utrace code cleaner. I recall you wanted to rework something about tracehook_notify_jctl earlier too. Now is the time to revisit all that and clean the code up however seems best. It shouldn't be a problem to rewrite the last half of do_signal_stop() and one (or two) tracehook_*_jctl interfaces to be optimal for utrace. We should also think about having utrace_do_stop() change TASK_STOPPED into TASK_TRACED like the old ptrace_check_attach() does. That way SIGCONT just won't wake it up in the first place. I think the only reason I avoided that before may have been the dual code paths with old ptrace, but if we are now doing a cleanup that entirely replaces the old ptrace guts, that is not an issue. The existing utrace_wakeup logic for turning TASK_TRACED back into TASK_STOPPED might be OK as it is. The perhaps we don't actually need the ->stopped flag. It means exactly: ->state == TASK_TRACED || (->exit_state && !(->utrace_flags & _UTRACE_DEATH_EVENTS)) which can be checked under utrace->lock. What do you think? Thanks, Roland From holidays at netcabo.pt Sat Jul 25 03:36:38 2009 From: holidays at netcabo.pt (=?iso-8859-1?Q?Way=20Out=20-=20Tourism=20Online?=) Date: Fri, 24 Jul 2009 23:36:38 -0400 Subject: =?iso-8859-1?q?O_melhor_pre=E7o_-_The_best_price?= Message-ID: <20090725043629.C577BB8F.F48CE9D0@192.168.0.15> MAIL ERROR -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: image/jpeg Size: 202263 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: image/jpeg Size: 29954 bytes Desc: not available URL: From railroaders at motopuzzle.cz Sat Jul 25 19:17:36 2009 From: railroaders at motopuzzle.cz (Locke Letofsky) Date: Sat, 25 Jul 2009 19:17:36 +0000 Subject: biographic Message-ID: <43fc042e620b8a6136toothpaste@motopuzzle.cz> Choosinng Veery sexy Panties.www.molopo .net From uranism at thedocshop.com Mon Jul 27 02:12:39 2009 From: uranism at thedocshop.com (Frankum) Date: Mon, 27 Jul 2009 02:12:39 +0000 Subject: dupes Message-ID: <365fadd233d4387d2139b9474dfe_taoism@thedocshop.com> Doing waAy With 'The Talk'.www.newway9 com From oleg at redhat.com Mon Jul 27 19:10:03 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 27 Jul 2009 21:10:03 +0200 Subject: Q: utrace && ptrace_check_attach() In-Reply-To: <20090725001933.861BEE7EA@magilla.sf.frob.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> Message-ID: <20090727191003.GA15804@redhat.com> On 07/24, Roland McGrath wrote: > > > Roland, can we just remove all code which plays with ->stopped in > > utrace_report_jctl() and utrace_get_signal(), and do something like > [...] > > @@ -1602,6 +1602,16 @@ static int do_signal_stop(int signr) > > do { > > schedule(); > > } while (try_to_freeze()); > > + > > + // needs a tracehook helper > > + if (utrace->stopped) { > > Hmm. I guess we could. I think my original thinking was just minimizing > the number of places in the core kernel code where we inserted any > tracehook call, keeping them to about exactly where the ptrace hooks had > been. But now I'd say it is certainly fine to insert another hook in the > signals code if it keeps the utrace code cleaner. Good. In any case I believe utrace_get_signal() and utrace_report_jctl() should not play with ->stopped. This really simplifies the code and what ->stopped == T means. > I recall you wanted to rework something about tracehook_notify_jctl earlier > too. Now is the time to revisit all that and clean the code up however > seems best. It shouldn't be a problem to rewrite the last half of > do_signal_stop() and one (or two) tracehook_*_jctl interfaces to be optimal > for utrace. OK, I'll send the patch. _IIRC_, this patch should also fix some races with SIGNAL_STOP_STOPPED which is temporary cleared by utrace_report_jctl(). > We should also think about having utrace_do_stop() change TASK_STOPPED into > TASK_TRACED like the old ptrace_check_attach() does. That way SIGCONT just > won't wake it up in the first place. Yes, I thought about this too. But until we kill the ->stopped flag as you suggested, > It means exactly: > ->state == TASK_TRACED || > (->exit_state && !(->utrace_flags & _UTRACE_DEATH_EVENTS)) we still have to clear ->stopped after wake up from TASK_STOPPED. (this change also breaks ptrace_resume() but this is fixeable). But personally I never liked the fact that ptrace_check_attach() does s/TASK_STOPPED/TASK_TRACED/. Because I think this creates the unfixeable ptrace && jctl-group-stop problems. The bookkeeping of ->group_stop_count in utrace_stop() (and in ptrace_stop()) is just wrong and imho should be removed. And do_signal_stop() should not take TASK_TRACED threads into account. This leads to another question which I was going to ask later, I'll send another email. Oleg. From roland at redhat.com Mon Jul 27 20:01:26 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 27 Jul 2009 13:01:26 -0700 (PDT) Subject: Q: utrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Monday, 27 July 2009 21:10:03 +0200 <20090727191003.GA15804@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> Message-ID: <20090727200126.144D54213C@magilla.sf.frob.com> > Good. In any case I believe utrace_get_signal() and utrace_report_jctl() > should not play with ->stopped. This really simplifies the code and > what ->stopped == T means. I am open to any such sort of clean-up. If you change something that had a special rationale, I'll explain what it was so we address the original intent. > Yes, I thought about this too. > > But until we kill the ->stopped flag as you suggested, > > > It means exactly: > > ->state == TASK_TRACED || > > (->exit_state && !(->utrace_flags & _UTRACE_DEATH_EVENTS)) > > we still have to clear ->stopped after wake up from TASK_STOPPED. Yes. > (this change also breaks ptrace_resume() but this is fixeable). I can't tell which code you are talking about here. But the only ptrace_resume I care about is the new one true ptrace based from scratch on cleaned-up utrace, which you haven't written yet. > But personally I never liked the fact that ptrace_check_attach() does > s/TASK_STOPPED/TASK_TRACED/. Because I think this creates the unfixeable > ptrace && jctl-group-stop problems. The bookkeeping of ->group_stop_count > in utrace_stop() (and in ptrace_stop()) is just wrong and imho should be > removed. And do_signal_stop() should not take TASK_TRACED threads into > account. Why do you think they are unfixable? The reason that switching into TASK_TRACED is good is that it (and only it) ensures that SIGCONT won't wake the thread up. As long as it's in TASK_STOPPED, any examination loop (prepare/finish_examine, or task_current_syscall, i.e. the "wait_task_inactive before and after" check for no csw) can experience a hiccup if a normal SIGCONT comes along. It seems far better that it just not wake up (i.e. any csw) while UTRACE_STOP, except for SIGKILL (and stray wake_up_process or whatever, but any of those are most-bets-off anyway and we hope few or none still exist). For do_signal_stop it's right to consider TASK_TRACED threads as stopped. The purpose of the group-stop bookkeeping is to make sure that when we declare the whole process stopped (SIGNAL_STOP_STOPPED, send SIGCHLD to real parent, wait_task_stopped reports, etc.) then no more user instructions will run in any thread, nor any user syscall in progress complete. If some threads are in TASK_TRACED, then they won't run any such things (if we get the bookkeeping right). It would be wrong to make the whole-process stop fail to finish while the debugger holds one thread in TASK_TRACED. The bookkeeping should ensure that when a TASK_TRACED thread was counted as stopped, then utrace never wakes it up but instead puts it in TASK_STOPPED so it's as if it had been in TASK_STOPPED throughout. If SIGCONT came along and woke the other threads up, then the whole process can safely be considered resumed when every thread is out of TASK_STOPPED--either resumed, or still in TASK_TRACED because of UTRACE_STOP. Then UTRACE_RESUME et al must be sure that each task winds up correctly either running or in TASK_STOPPED as now appropriate for the process. I'm open to all manner of reorganization of the bookkeeping. But please explain how what you propose addresses these ideas. Thanks, Roland From oleg at redhat.com Mon Jul 27 20:30:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 27 Jul 2009 22:30:30 +0200 Subject: Q: jctl-stop && utrace_wakeup() In-Reply-To: <20090727191003.GA15804@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> Message-ID: <20090727203030.GA19187@redhat.com> utrace_wakeup: if (likely(task_is_stopped_or_traced(target))) { if (target->signal->flags & SIGNAL_STOP_STOPPED) target->state = TASK_STOPPED; else wake_up_state(target, __TASK_STOPPED | __TASK_TRACED); } Let's forget about ptrace for the moment. The code above means that utrace can't wake up the tracee if it was group-stopped. This looks reasonable, but in that case I don't understand what should we do if ->report_signal() returns UTRACE_SIGNAL_STOP. I mean, the attached engine can stop the tracee but can't wake it up? However, utrace_wakeup() is not right. It only checks SIGNAL_STOP_STOPPED, but doesn't check ->group_stop_count. But, otoh, we need no checks here, utrace_wakeup() can just do wake_up_state(__TASK_TRACED) and nothing more (remember, I am ignoring ptrace issues). but ptrace_resume() is different, it should wake up the tracee, that is why it does: if (task_is_stopped(child)) { spin_lock_irq(&child->sighand->siglock); child->signal->flags &= ~SIGNAL_STOP_STOPPED; spin_unlock_irq(&child->sighand->siglock); } and this code is wrong again: what if check ->group_stop_count != 0? In that case SIGNAL_STOP_STOPPED can be set later, when utrace_wakeup() is called. (note that we have more problems with utrace_report_jctl() playing with task->state/signal->flags, should be fixed by the cleanups discussed in another thread). What can we do? I don't see any solution. Oleg. From oleg at redhat.com Mon Jul 27 22:36:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 28 Jul 2009 00:36:32 +0200 Subject: Q: utrace && ptrace_check_attach() In-Reply-To: <20090727200126.144D54213C@magilla.sf.frob.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727200126.144D54213C@magilla.sf.frob.com> Message-ID: <20090727223632.GA24531@redhat.com> On 07/27, Roland McGrath wrote: > > > (this change also breaks ptrace_resume() but this is fixeable). > > I can't tell which code you are talking about here. But the only > ptrace_resume I care about is the new one true ptrace based from > scratch on cleaned-up utrace, which you haven't written yet. I meant ptrace_resume()->task_is_stopped() check in ptrace_utrace.patch. > > But personally I never liked the fact that ptrace_check_attach() does > > s/TASK_STOPPED/TASK_TRACED/. Because I think this creates the unfixeable > > ptrace && jctl-group-stop problems. The bookkeeping of ->group_stop_count > > in utrace_stop() (and in ptrace_stop()) is just wrong and imho should be > > removed. And do_signal_stop() should not take TASK_TRACED threads into > > account. > > Why do you think they are unfixable? The reason that switching into > TASK_TRACED is good is that it (and only it) ensures that SIGCONT > won't wake the thread up. As long as it's in TASK_STOPPED, any > examination loop (prepare/finish_examine, or task_current_syscall, > i.e. the "wait_task_inactive before and after" check for no csw) > can experience a hiccup if a normal SIGCONT comes along. It seems far > better that it just not wake up (i.e. any csw) while UTRACE_STOP, Yes, this is true. > For do_signal_stop it's right to consider TASK_TRACED threads as > stopped. The purpose of the group-stop bookkeeping is to make sure > that when we declare the whole process stopped (SIGNAL_STOP_STOPPED, > send SIGCHLD to real parent, wait_task_stopped reports, etc.) then no > more user instructions will run in any thread, nor any user syscall in > progress complete. If some threads are in TASK_TRACED, then they > won't run any such things (if we get the bookkeeping right). It would > be wrong to make the whole-process stop fail to finish while the > debugger holds one thread in TASK_TRACED. Yes, the whole-process stop will be delayed until the debugger wakes up the tracee and it sees signal_pending(). Not nice, agreed, but probably not too bad. The debugger doesn't really care. As for real parent, it will be confused in any case. It can't assume the whole process is really stopped, debugger can wake up a thread at any moment. > The bookkeeping should ensure that when a TASK_TRACED thread was > counted as stopped, But we can't know if it was already counted or not. And note that utrace_stop() doesn't set SIGNAL_STOP_STOPPED and doesn't notify if ->group_stop_count becomes 0. > then utrace never wakes it up but instead puts it > in TASK_STOPPED only if group-stop is already completed. > I'm open to all manner of reorganization of the bookkeeping. > But please explain how what you propose addresses these ideas. I meant --- kernel/signal.c +++ kernel/signal.c @@ -1571,7 +1571,7 @@ static int do_signal_stop(int signr) * so this check has no races. */ if (!(t->flags & PF_EXITING) && - !task_is_stopped_or_traced(t)) { + !task_is_stopped(t)) { stop_count++; signal_wake_up(t, 0); } --- kernel/utrace.c +++ kernel/utrace.c @@ -409,13 +409,6 @@ static bool utrace_stop(struct task_stru utrace->stopped = 1; __set_current_state(TASK_TRACED); - /* - * If there is a group stop in progress, - * we must participate in the bookkeeping. - */ - if (task->signal->group_stop_count > 0) - --task->signal->group_stop_count; - spin_unlock_irq(&task->sighand->siglock); spin_unlock(&utrace->lock); for the start. Or we can ignore all these problems, there are not new. So. Let's change utrace_do_stop() to set TASK_TRACED, --- kernel/utrace.c +++ kernel/utrace.c @@ -797,8 +797,10 @@ static bool utrace_do_stop(struct task_s } else if (task_is_stopped(target)) { /* * Stopped is considered quiescent; when it wakes up, it will - * go through utrace_get_signal() before doing anything else. + * go through utrace_report_jctl() or utrace_get_signal() + * before doing anything else. */ + __set_task_state(target, TASK_TRACED); utrace->stopped = stopped = true; } else if (!utrace->report && !utrace->interrupt) { utrace->report = 1; @@ -1913,6 +1915,15 @@ int utrace_get_signal(struct task_struct int signr; utrace = &task->utrace; + + if (unlikely(utrace->stopped)) { + spin_unlock_irq(&task->sighand->siglock); + spin_lock(&utrace->lock); + utrace->stopped = 0; + spin_unlock(&utrace->lock); + spin_lock_irq(&task->sighand->siglock); + } + if (utrace->interrupt || utrace->report || utrace->signal_handler) { /* * We've been asked for an explicit report before we @@ -1937,7 +1948,6 @@ int utrace_get_signal(struct task_struct * interrupt path, so clear the flags asking for those. */ utrace->interrupt = utrace->report = utrace->signal_handler = 0; - utrace->stopped = 0; /* * Make sure signal_pending() only returns true @@ -1966,22 +1976,13 @@ int utrace_get_signal(struct task_struct event = 0; ka = NULL; memset(return_ka, 0, sizeof *return_ka); - } else if ((task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) == 0 && - !utrace->stopped) { + } else if ((task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) == 0) { /* * If no engine is interested in intercepting signals, * let the caller just dequeue them normally. */ return 0; } else { - if (unlikely(utrace->stopped)) { - spin_unlock_irq(&task->sighand->siglock); - spin_lock(&utrace->lock); - utrace->stopped = 0; - spin_unlock(&utrace->lock); - spin_lock_irq(&task->sighand->siglock); - } - /* * Steal the next signal so we can let tracing engines * examine it. From the signal number and sigaction, Or do you think it is better to add tracehook_finish_stop() helper which is called by do_signal_stop() to clear ->stopped ? As you pointed out we can remove ->stopped, but I am not sure we should do this now. BTW, can't finish_utrace_stop() check utrace->stopped lockless? Oleg. From oleg at redhat.com Mon Jul 27 23:35:07 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 28 Jul 2009 01:35:07 +0200 Subject: [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction In-Reply-To: <20090727191003.GA15804@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> Message-ID: <20090727233507.GA27478@redhat.com> On 07/27, Oleg Nesterov wrote: > > On 07/24, Roland McGrath wrote: > > > > I recall you wanted to rework something about tracehook_notify_jctl earlier > > too. Now is the time to revisit all that and clean the code up however > > seems best. It shouldn't be a problem to rewrite the last half of > > do_signal_stop() and one (or two) tracehook_*_jctl interfaces to be optimal > > for utrace. > > OK, I'll send the patch. _IIRC_, this patch should also fix some races > with SIGNAL_STOP_STOPPED which is temporary cleared by utrace_report_jctl(). Please find the patch below, compile tested. Assuming you agree with this change... I don't know how it should be merged. Probably the change in signal.c should be sent separately, but this breaks -mm tree. ------------------------------------------------------------------------------ [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction do_signal_stop() can call utrace_report_jctl() before decrementing ->group_stop_count and setting TASK_STOPPED/SIGNAL_STOP_STOPPED. This allows to greatly simplify utrace_report_jctl() and avoid playing with group-stop bookkeeping twice. Signed-off-by: Oleg Nesterov ---- kernel/signal.c | 29 +++++++++++------------------ kernel/utrace.c | 20 -------------------- 2 files changed, 11 insertions(+), 38 deletions(-) --- __UTRACE/kernel/signal.c~JCTL 2009-07-13 17:44:27.000000000 +0200 +++ __UTRACE/kernel/signal.c 2009-07-28 01:20:17.000000000 +0200 @@ -1682,16 +1682,9 @@ void ptrace_notify(int exit_code) static int do_signal_stop(int signr) { struct signal_struct *sig = current->signal; - int stop_count; int notify; - if (sig->group_stop_count > 0) { - /* - * There is a group stop in progress. We don't need to - * start another one. - */ - stop_count = --sig->group_stop_count; - } else { + if (!sig->group_stop_count) { struct task_struct *t; if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || @@ -1703,7 +1696,7 @@ static int do_signal_stop(int signr) */ sig->group_exit_code = signr; - stop_count = 0; + sig->group_stop_count = 1; for (t = next_thread(current); t != current; t = next_thread(t)) /* * Setting state to TASK_STOPPED for a group @@ -1712,25 +1705,25 @@ static int do_signal_stop(int signr) */ if (!(t->flags & PF_EXITING) && !task_is_stopped_or_traced(t)) { - stop_count++; + sig->group_stop_count++; signal_wake_up(t, 0); } - sig->group_stop_count = stop_count; } - if (stop_count == 0) - sig->flags = SIGNAL_STOP_STOPPED; - current->exit_code = sig->group_exit_code; - __set_current_state(TASK_STOPPED); - /* * If there are no other threads in the group, or if there is * a group stop in progress and we are the last to stop, * report to the parent. When ptraced, every thread reports itself. */ - notify = tracehook_notify_jctl(stop_count == 0 ? CLD_STOPPED : 0, - CLD_STOPPED); + notify = sig->group_stop_count == 1 ? CLD_STOPPED : 0; + notify = tracehook_notify_jctl(notify, CLD_STOPPED); + if (sig->group_stop_count) { + if (!--sig->group_stop_count) + sig->flags = SIGNAL_STOP_STOPPED; + current->exit_code = sig->group_exit_code; + __set_current_state(TASK_STOPPED); + } spin_unlock_irq(¤t->sighand->siglock); if (notify) { --- __UTRACE/kernel/utrace.c~JCTL 2009-06-11 17:46:26.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-28 01:20:17.000000000 +0200 @@ -1606,18 +1606,7 @@ void utrace_report_jctl(int notify, int struct task_struct *task = current; struct utrace *utrace = task_utrace_struct(task); INIT_REPORT(report); - bool stop = task_is_stopped(task); - /* - * We have to come out of TASK_STOPPED in case the event report - * hooks might block. Since we held the siglock throughout, it's - * as if we were never in TASK_STOPPED yet at all. - */ - if (stop) { - __set_current_state(TASK_RUNNING); - task->signal->flags &= ~SIGNAL_STOP_STOPPED; - ++task->signal->group_stop_count; - } spin_unlock_irq(&task->sighand->siglock); /* @@ -1646,16 +1635,7 @@ void utrace_report_jctl(int notify, int REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), report_jctl, what, notify); - /* - * Retake the lock, and go back into TASK_STOPPED - * unless the stop was just cleared. - */ spin_lock_irq(&task->sighand->siglock); - if (stop && task->signal->group_stop_count > 0) { - __set_current_state(TASK_STOPPED); - if (--task->signal->group_stop_count == 0) - task->signal->flags |= SIGNAL_STOP_STOPPED; - } } /* From roland at redhat.com Tue Jul 28 00:03:40 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 27 Jul 2009 17:03:40 -0700 (PDT) Subject: Q: utrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Tuesday, 28 July 2009 00:36:32 +0200 <20090727223632.GA24531@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727200126.144D54213C@magilla.sf.frob.com> <20090727223632.GA24531@redhat.com> Message-ID: <20090728000340.7DEC84213C@magilla.sf.frob.com> > I meant ptrace_resume()->task_is_stopped() check in ptrace_utrace.patch. Oh. I think that was an attempt at ptrace bug-compatibility. Like I keep saying, don't take any code in that patch seriously. > Yes, the whole-process stop will be delayed until the debugger > wakes up the tracee and it sees signal_pending(). I don't think we want this. > Not nice, agreed, but probably not too bad. The debugger doesn't > really care. As for real parent, it will be confused in any case. No, it needn't be. > It can't assume the whole process is really stopped, debugger > can wake up a thread at any moment. No, it can't. That's what "get the bookkeeping right" means. It the debugger uses UTRACE_RESUME et al, then that thread moves from TASK_TRACED into TASK_STOPPED and still never runs. > > The bookkeeping should ensure that when a TASK_TRACED thread was > > counted as stopped, > > But we can't know if it was already counted or not. Sure we can. The group_stop_count is set by the stop-instigator while it holds siglock and checks every thread's ->state. All transitions into or out of TASK_TRACED are done holding the siglock. When you take siglock and see there is a stop in progress, then you know the thread's TASK_TRACED was counted as stopped in setting up that stop. > And note that utrace_stop() doesn't set SIGNAL_STOP_STOPPED and doesn't > notify if ->group_stop_count becomes 0. We can fix this. > > then utrace never wakes it up but instead puts it > > in TASK_STOPPED > > only if group-stop is already completed. Or in progress. > Or we can ignore all these problems, there are not new. No, let's get it right for a change! ;-) > So. Let's change utrace_do_stop() to set TASK_TRACED, I like that direction. > Or do you think it is better to add tracehook_finish_stop() helper which is > called by do_signal_stop() to clear ->stopped ? Let's do it however makes the code taken all together come out cleanest. >From what you said before, it sounds like tracehook_finish_stop() would help with that. > As you pointed out we can remove ->stopped, but I am not sure we should do > this now. Sure, we can take it one step at a time. Once we have cleaned up all the stop handling, we can see what this flag is still doing for us. > BTW, can't finish_utrace_stop() check utrace->stopped lockless? You tell me! Thanks, Roland From roland at redhat.com Tue Jul 28 00:17:20 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 27 Jul 2009 17:17:20 -0700 (PDT) Subject: Q: jctl-stop && utrace_wakeup() In-Reply-To: Oleg Nesterov's message of Monday, 27 July 2009 22:30:30 +0200 <20090727203030.GA19187@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727203030.GA19187@redhat.com> Message-ID: <20090728001720.D08664213C@magilla.sf.frob.com> > utrace_wakeup: > > if (likely(task_is_stopped_or_traced(target))) { > if (target->signal->flags & SIGNAL_STOP_STOPPED) > target->state = TASK_STOPPED; > else > wake_up_state(target, __TASK_STOPPED | __TASK_TRACED); > } Looks like it should look at group_stop_count too. > Let's forget about ptrace for the moment. Gladly! ;-) > The code above means that utrace can't wake up the tracee if it was > group-stopped. This looks reasonable, but in that case I don't understand > what should we do if ->report_signal() returns UTRACE_SIGNAL_STOP. I mean, > the attached engine can stop the tracee but can't wake it up? I'm not sure I follow the question. UTRACE_SIGNAL_STOP means to act like a normal SIGSTOP signal, i.e. initiate a group-stop (with group_exit_code set to info->si_signo). You do that when you are passing on a real stop signal you decided not to intercept, or if you want to simulate a signal. That results in a normal job stop, unrelated to UTRACE_STOP. If you want it to wake up from that, you send it a SIGCONT. If report_signal returns UTRACE_SIGNAL_STOP | UTRACE_STOP, that (as always) means "do this signal action, then go into utrace-stop". The signal action is the group stop, so with today's code you go into TASK_STOPPED as normal, but engine_wants_stop() is set so it will go into utrace_stop() when it resumes. With the new plan of always using TASK_TRACED for UTRACE_STOP, then UTRACE_SIGNAL_STOP|UTRACE_STOP should do the group-stop bookkeeping/notify and then go into TASK_TRACED. i.e., as if it had finished processing the stop signal and then you called utrace_control(,,UTRACE_STOP). > However, utrace_wakeup() is not right. It only checks SIGNAL_STOP_STOPPED, > but doesn't check ->group_stop_count. But, otoh, we need no checks here, > utrace_wakeup() can just do wake_up_state(__TASK_TRACED) and nothing more > (remember, I am ignoring ptrace issues). For new the plan it needs to change back to TASK_STOPPED when appropriate. > but ptrace_resume() is different, it should wake up the tracee, that is > why it does: But I've already forgotten about ptrace! :-) > if (task_is_stopped(child)) { > spin_lock_irq(&child->sighand->siglock); > child->signal->flags &= ~SIGNAL_STOP_STOPPED; > spin_unlock_irq(&child->sighand->siglock); > } All this is bug-compatibility with traditional ptrace where it uses wake_up_process() unconditionally without regard to all the bookkeeping. But utrace never ignores the proper bookkeeping, so we further confuse things trying to get the traditional userland-visible results. Probably the right thing to will be to fix the upstream ptrace semantics and figure out any userland issues with that, and then we won't have any kludge like this for utrace-based ptrace. > and this code is wrong again: what if check ->group_stop_count != 0? > In that case SIGNAL_STOP_STOPPED can be set later, when utrace_wakeup() > is called. Its kinds of "wrong" only have to be no worse than wake_up_process(), which is many kinds of wrong, so this has been a hazy area. > What can we do? I don't see any solution. Let's iron out what we think are intelligent and proper semantics at the utrace level, and then we can revisit the ptrace oddities later. It has never played very well with job control, so some changes are probably in order to achieve anything sane enough to be specified precisely. Thanks, Roland From roland at redhat.com Tue Jul 28 00:36:35 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 27 Jul 2009 17:36:35 -0700 (PDT) Subject: [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction In-Reply-To: Oleg Nesterov's message of Tuesday, 28 July 2009 01:35:07 +0200 <20090727233507.GA27478@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727233507.GA27478@redhat.com> Message-ID: <20090728003635.B08284213C@magilla.sf.frob.com> > Assuming you agree with this change... I don't know how it should be merged. > Probably the change in signal.c should be sent separately, but this breaks > -mm tree. The relevant -mm differences are just in one patch that folds finish_stop into do_signal_stop, right? If I can apply just that one patch to the Linus tree (i.e. v2.6.31-rc4+) and then yours without conflicts, that does just fine. The signal.c change should go upstream ASAP, and that patch should also include a change to the tracehook_notify_jctl kerneldoc so that it is accurate about the locking et al. (I am assuming you are confident that we won't want to revamp do_signal_stop again differently for this later.) > - notify = tracehook_notify_jctl(stop_count == 0 ? CLD_STOPPED : 0, > - CLD_STOPPED); > + notify = sig->group_stop_count == 1 ? CLD_STOPPED : 0; > + notify = tracehook_notify_jctl(notify, CLD_STOPPED); > > + if (sig->group_stop_count) { > + if (!--sig->group_stop_count) This warrants a comment here about the first if. The only reason it is there is that tracehook_notify_jctl is allowed to drop and reacquire the siglock, which makes the sig->group_stop_count = 1 logic et al beforehand very important. Thanks, Roland From oleg at redhat.com Tue Jul 28 00:36:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 28 Jul 2009 02:36:54 +0200 Subject: Q: utrace && ptrace_check_attach() In-Reply-To: <20090728000340.7DEC84213C@magilla.sf.frob.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727200126.144D54213C@magilla.sf.frob.com> <20090727223632.GA24531@redhat.com> <20090728000340.7DEC84213C@magilla.sf.frob.com> Message-ID: <20090728003654.GA29137@redhat.com> On 07/27, Roland McGrath wrote: > > No, it can't. That's what "get the bookkeeping right" means. > It the debugger uses UTRACE_RESUME et al, then that thread moves > from TASK_TRACED into TASK_STOPPED and still never runs. Ah. In that case yes, we can make this all consistent. But I am not sure I understand you right, please see below. > > > The bookkeeping should ensure that when a TASK_TRACED thread was > > > counted as stopped, > > > > But we can't know if it was already counted or not. > > Sure we can. The group_stop_count is set by the stop-instigator while it > holds siglock and checks every thread's ->state. All transitions into or > out of TASK_TRACED are done holding the siglock. When you take siglock and > see there is a stop in progress, then you know the thread's TASK_TRACED was > counted as stopped in setting up that stop. Yes, yes, sure. But currently ptrace can wake up the tracee and then later it can be ptrace_stop()'ed again, in this case we can decrement ->group_stop_count twice for the same thread. OK, forget about mt issues. Do you really mean PTRACE_CONT/etc must _not_ wake up SIGNAL_STOP_STOPPED tracee ? This would be nice perhaps, but this means a serious user-visible change. Or I misunderstood you? > > And note that utrace_stop() doesn't set SIGNAL_STOP_STOPPED and doesn't > > notify if ->group_stop_count becomes 0. > > We can fix this. sure, this is minor. > > Or do you think it is better to add tracehook_finish_stop() helper which is > > called by do_signal_stop() to clear ->stopped ? > > Let's do it however makes the code taken all together come out cleanest. > From what you said before, it sounds like tracehook_finish_stop() would > help with that. OK, I'll send the patch. > > BTW, can't finish_utrace_stop() check utrace->stopped lockless? > > You tell me! I think it can. finish_utrace_stop() can't miss ->stopped if it was not cleared, it was set by us. When finish_utrace_stop() takes utrace->lock to clear ->stopped it can be already cleared by utrace_wakeup() but we don't care. And, if ->stopped == F, nobody (utrace_do_stop() actually) can set it. If this was possible we have a bug anyway. Oleg. From roland at redhat.com Tue Jul 28 00:49:27 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 27 Jul 2009 17:49:27 -0700 (PDT) Subject: Q: utrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Tuesday, 28 July 2009 02:36:54 +0200 <20090728003654.GA29137@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727200126.144D54213C@magilla.sf.frob.com> <20090727223632.GA24531@redhat.com> <20090728000340.7DEC84213C@magilla.sf.frob.com> <20090728003654.GA29137@redhat.com> Message-ID: <20090728004927.8922D4213C@magilla.sf.frob.com> > But currently ptrace can wake up the tracee and then later it can be > ptrace_stop()'ed again, in this case we can decrement ->group_stop_count > twice for the same thread. The behavior or the bookkeeping need to change so they are consistent. > OK, forget about mt issues. Do you really mean PTRACE_CONT/etc must _not_ > wake up SIGNAL_STOP_STOPPED tracee ? This would be nice perhaps, but this > means a serious user-visible change. I'm talking about the UTRACE_STOP/utrace_control behavior here. When we implement ptrace on top and then get to the nasty corners of strange compatibility with old ptrace, we can figure out what the exact user-visible ptrace semantics need to be. We might just do those cleanly on top, or we might need some special-case ptrace fiddling. But what we won't do is have ptrace do anything that confuses the utrace bookkeeping or the signals bookkeeping, like the current wake_up_process() does. > > Let's do it however makes the code taken all together come out cleanest. > > From what you said before, it sounds like tracehook_finish_stop() would > > help with that. > > OK, I'll send the patch. Use tracehook_*_jctl for the name, so it pairs with notify_jctl (and/or change both names). I avoid using "stop" in the tracehook.h names because it's not inherently clear when that means "job control stop semantics" and when that means other kinds of stopping (like utrace_stop/ptrace_stop). jctl keeps it clear that this is only part of the code paths used for POSIX job control stops. > I think it can. Ok! Thanks, Roland From oleg at redhat.com Tue Jul 28 01:05:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 28 Jul 2009 03:05:22 +0200 Subject: Q: jctl-stop && utrace_wakeup() In-Reply-To: <20090728001720.D08664213C@magilla.sf.frob.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727203030.GA19187@redhat.com> <20090728001720.D08664213C@magilla.sf.frob.com> Message-ID: <20090728010522.GA30526@redhat.com> On 07/27, Roland McGrath wrote: > > > utrace_wakeup: > > > > if (likely(task_is_stopped_or_traced(target))) { > > if (target->signal->flags & SIGNAL_STOP_STOPPED) > > target->state = TASK_STOPPED; > > else > > wake_up_state(target, __TASK_STOPPED | __TASK_TRACED); > > } > > Looks like it should look at group_stop_count too. Yes. > > The code above means that utrace can't wake up the tracee if it was > > group-stopped. This looks reasonable, but in that case I don't understand > > what should we do if ->report_signal() returns UTRACE_SIGNAL_STOP. I mean, > > the attached engine can stop the tracee but can't wake it up? > > I'm not sure I follow the question. I meant, we can't wake up via utrace_control(), > If you want it to > wake up from that, you send it a SIGCONT. Yes sure. > > if (task_is_stopped(child)) { > > spin_lock_irq(&child->sighand->siglock); > > child->signal->flags &= ~SIGNAL_STOP_STOPPED; > > spin_unlock_irq(&child->sighand->siglock); > > } > > All this is bug-compatibility with traditional ptrace where it uses > wake_up_process() unconditionally without regard to all the bookkeeping. OK. I guess this answers my "do you really want a user-visible change" question in another thread. > Probably the right thing to will be to fix the upstream ptrace semantics > and figure out any userland issues with that, and then we won't have any > kludge like this for utrace-based ptrace. Oh. I bet, if we change the current behaviour, we will have bug-reports ;) Oleg. From oleg at redhat.com Tue Jul 28 01:25:34 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 28 Jul 2009 03:25:34 +0200 Subject: [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction In-Reply-To: <20090728003635.B08284213C@magilla.sf.frob.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727233507.GA27478@redhat.com> <20090728003635.B08284213C@magilla.sf.frob.com> Message-ID: <20090728012534.GA31866@redhat.com> On 07/27, Roland McGrath wrote: > > > Assuming you agree with this change... I don't know how it should be merged. > > Probably the change in signal.c should be sent separately, but this breaks > > -mm tree. > > The relevant -mm differences are just in one patch that folds finish_stop > into do_signal_stop, right? Ah. I forgot signals-tracehook_notify_jctl-change.patch is still pending in -mm. > If I can apply just that one patch to the > Linus tree (i.e. v2.6.31-rc4+) and then yours without conflicts, that does > just fine. Or you can just merge these 2 patches, perhaps this would be better. > The signal.c change should go upstream ASAP, and that patch should also > include a change to the tracehook_notify_jctl kerneldoc so that it is > accurate about the locking et al. Confused, signals-tracehook_notify_jctl-change.patch already updated the comment? > > - notify = tracehook_notify_jctl(stop_count == 0 ? CLD_STOPPED : 0, > > - CLD_STOPPED); > > + notify = sig->group_stop_count == 1 ? CLD_STOPPED : 0; > > + notify = tracehook_notify_jctl(notify, CLD_STOPPED); > > > > + if (sig->group_stop_count) { > > + if (!--sig->group_stop_count) > > This warrants a comment here about the first if. The only reason it is > there is that tracehook_notify_jctl is allowed to drop and reacquire the > siglock, and SIGCONT may come in between, > which makes the sig->group_stop_count = 1 logic et al beforehand > very important. Agreed, will resend... Oleg. From roland at redhat.com Tue Jul 28 01:35:07 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 27 Jul 2009 18:35:07 -0700 (PDT) Subject: Q: jctl-stop && utrace_wakeup() In-Reply-To: Oleg Nesterov's message of Tuesday, 28 July 2009 03:05:22 +0200 <20090728010522.GA30526@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727203030.GA19187@redhat.com> <20090728001720.D08664213C@magilla.sf.frob.com> <20090728010522.GA30526@redhat.com> Message-ID: <20090728013507.ACAF94213C@magilla.sf.frob.com> > Oh. I bet, if we change the current behaviour, we will have bug-reports ;) We can consult with the gdb folks (Jan) and make sure there are ptrace-tests cases expressing everything that should matter to userland. Then we can work out so those tests match the old behavior, or if we find places with strong reasons it should change, we can hash those out. Thanks, Roland From roland at redhat.com Tue Jul 28 01:39:17 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 27 Jul 2009 18:39:17 -0700 (PDT) Subject: [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction In-Reply-To: Oleg Nesterov's message of Tuesday, 28 July 2009 03:25:34 +0200 <20090728012534.GA31866@redhat.com> References: <20090720172240.GA22459@redhat.com> <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727233507.GA27478@redhat.com> <20090728003635.B08284213C@magilla.sf.frob.com> <20090728012534.GA31866@redhat.com> Message-ID: <20090728013917.120514213C@magilla.sf.frob.com> > Ah. I forgot signals-tracehook_notify_jctl-change.patch is still pending in > -mm. Perhaps we should just rejigger all these together into one new patch (or two, whatever) before akpm submits any of them. > Or you can just merge these 2 patches, perhaps this would be better. As long as we have akpm drop/update the any conflicting ones, sure. > > The signal.c change should go upstream ASAP, and that patch should also > > include a change to the tracehook_notify_jctl kerneldoc so that it is > > accurate about the locking et al. > > Confused, signals-tracehook_notify_jctl-change.patch already updated the > comment? I was looking at the Linus tree, not the -mm tree (I always do). If that prerequisite patch (or merged rejiggered patch or whatever) updates the comments that is fine. I was also just noticing the other callers of tracehook_notify_jctl, which should all be rejiggered as makes most sense for the locking change (maybe that pending patch already did that). > > This warrants a comment here about the first if. The only reason it is > > there is that tracehook_notify_jctl is allowed to drop and reacquire the > > siglock, > > and SIGCONT may come in between, Right, or the various other things (SIGKILL, etc.). Thanks, Roland From cmtechnical at bsnl.in Tue Jul 28 06:01:01 2009 From: cmtechnical at bsnl.in (Organization) Date: Tue, 28 Jul 2009 11:31:01 +0530 Subject: [ALERT]: It's the time to come out on streets and stop the complete nation on it's place - Take immediate actions at once with full force. Message-ID: <20090725.DOHHSBCPJSRVGQMC@bsnl.in> Respected Friends, It's my pleasure to get in touch with you. This email is about security and future safety of your family, your child, your wife, your friends and relatives. It has become very necessary to take action now and get united else there will be no one behind you to take care of your family, if any thing happens to you in future, due to the Islamic Terrorism Related Activities that are spreading all over the world with millions and millions of terrorists joining these islamic terrorism related organizations. 1/4th of the population of earth contains members who are working with thousands and thousands of Islamic Organizations to help them to spread terrorism. If we all are not united today then the day is not far when they all are going to over ride all of us and our childrens. So, better take action now to secure your and your children and family future. If you don't fight for your freedom today then there will be no one on the earth, to fight for the freedom of your children in future, from the corrupt politicians, from the terrorism and from the criminals. We all can together fight together against terrorism, against crime, against corrupt political peoples, Only when we decide to remain united by forgetting the religious boundaries and the national boundaries. This is a step which I am trying for human safety, future and security. Come and join us as soon as you can, before it's too late. Agar Aaj Aap Apne Ghar Mein Chup-Chaap Baithe Rahoge, Toh Phir Kal Aapke Baccho Ko Help Karne Wala Koi Nahin Hoga. Aisi Paristhiti Paida Ho, Isse Pehle Is United and Peaceful Organization Ka, Saath Do Aur Immediately Jyada Soche Bina Join Karo, Isi Mein Hum Sab Ki Bhalai Hai, Aur Agar Aapko Meri Baatein Bakwaas Lagti Hai, Toh Phir Mein Faisla Aap Par Chodta Hoon, Kya Karna Chahoge, Aane Wali Barbaadi Ka Intzaar Ya Phir Usse Makabla Karne Ki Tyaari? Freedom of Rights Ke Tahat Faisla Aapka Hai. I am running this campaign with a pure intention of unity amongst every citizen of every country so that in future we have the capacity and are able to face terrorism troubles. Millions and millions of people across the globe are today members of our organizations and I want to increase it more globally. No charge for joining this organization who has millions of members to help for your safety and security anytime, anywhere whenever you need help. No limits or restrictions of boundaries, caste, creed, religion because out organization's ultimate goal is peace and unity across the world. This is an email related to many issues, which are a part of your freedom and democratic rights. Before proceeding further, let me tell you something about me and give my introduction as well. The AIM is to work in co-operation, co-ordination and compromise with all of you regardless of whatsoever party or organization you belong. You are my and I am your - This is the philosophy I follow to create genuine long term relationship with everyone. If we all help each other together in co-operation, compromise and co-ordination with each other then we all will win our games. But seperately it's difficult task for all of us, which I hope all of you accept. Unity power is what I am trying to create through a genuine relationship with you. Anyone who wants to work in collabration with me under mutual understand which you think can be of great benefits for both sides then kindly do not hesitate to get in touch with me. I perform those tasks which no one can dare to perform. I like to do exclusive and unique things. I personally guarantee you for the best of the best once we start working together under co-operation and compromise with each other. Trust is a must for all the things. Even if you have any business related queries then feel free to get in touch with me. What I can do and what is my expertise is mentioned below in my digital signatures. I have the capacity to work 20 hours daily and can alone do work equivalent to 100000 persons. I have the capacity of non-stop work for 36-48 hours without sleep. I have experience in several industry sectors and can do most exclusive and unique things whether whatsoever is the level of competition. My introduction: I am an Information Security Expert with world records in hacking world's maximum websites live on air in a 3 hour non stop telecast with Honorable Rajat Sharma(Chairman, IndiaTV) in the presence of state minister of technology, technical experts, legal expert, stock exchange experts, corporate bodies, star media personnels and millions of public in a hot debate where I was alone to answer and there were so many peoples on other hand and we did the show with huge success. We did it for national interest and public interest. So, it was not considered as crime/offence because every country has a law that any action taken for the safety of public, citizen, national interest or with an intention to do something good for a large number of population, is not a crime. Then I worked for Honorable Chief Minister of Gujarat through a direct appointment from Mr. Narendra Modi without interference of any PA or IAS cadre officers or any other private level officers. He directly called me and communicated face to face, realized my capacity and immediately appointed me for a short term contract. So, in my eyes he is a great person because I have only seen such things in films and dramas till date, never in true life. But in India, Honorable Narendra Modiji was the first person whom I saw, who though having no relationship, not even knowing me and though I was a simple common man called me to meet face to face, gave me respect and then immediately gave me honour of work. Do you think this is a small contribution? When Narendra Modi won the 2007 state election in Gujarat, the media focused on Hindu-Muslim issues. But the truth about secret of Modi?s success lay in agriculture, an area completely neglected by political analysts. Between 2000-01 and 2007-08 agricultural value added grew at a phenomenal 9.6% per year (despite a major drought in 2002). This is more than double India?s agricultural growth rate, and much faster than Punjab?s farm growth in the green revolution heyday. Indeed, 9.6% agricultural growth is among the fastest rates recorded anywhere in the world. During the 2007 election campaign, the Congress slogan was ?chak de, chak de Gujarat?. I heard Modi say at a rally that his reply was ?check dam, check dam Gujarat.? But subsequently, under Modi, Gujarat has built ten times as many check dams! He could well say ?chak de, check dam?. Tell me about one such person which can be compared in politics with Honorable Modiji. He is my national hero, that's all I know if anyone asks me anything about a great political person. Similarly when I was a new person in my career field, at that time the Government was under control of BJP. At that time I got in touch with Honorable Prime Minister Vajpayeeji and Honorable President Abdul Kalaamji. The officers at that time immediately instantly gave me an appointment on reading my letter which had information about my expertise. I got the point, that they are those great personalities who want to truely without using publicity stunt want to help such talented people grow. This is true national bhakti in my view. I never even thought in my life as a common middle class person that I will get a chance to visit the so secured Rashtrapati Bhavan and their officers of concerned authorized departments. So, these are the true people whom I met when I decided to join the BJP, VHP, RSS and the Sangh Pariwaar. Here is when my mind started thinking that when these three persons on so higher designations are doing so much for a common middle class person who is totally unknown to them, then why even myself not start helping my nation? Today they are helping me, may be tomorrow due to my help someone can too decide to work for nation. In this way I committed to work for national interest by joing these parties. After the government of congress that was formed after Vajpayeeji, I several times mailed to PMO and Rashtrapati Bhavan several and several of letters of which I have all the copies to show my expertise, achievements and awards and asked them to give me some opportunities to work for nation. But they never never replied in their five years period till date. Recently I sent so many emails about key research on terrorism, no one cared at all. I have no data, no reply, no communications from anyone at all from Home Ministry after the Congress Government came into existence. So, this is where the true difference comes into existence and reality comes out, truth is seen and this when we know whom to trust and whom not. Then I worked for Army Intelligence also and the Leutinent Collonel used to come to my home as and when they felt my need to counterterrorism. I am also a technical intelligence expert and keep monitoring the terrorist activities and communications that take place on internet. From last three days also I am continously in touch with IB agencies and Home Ministry of India to give them news on terrorist activities. This is all about my work which I do as a freelancer. Today I have a global brand name and a huge reputation and relationship with millions of Indian Citizens. You may find me anywhere on internet with around 100000 or more results just about me. So, this is all about me. Just go through my Digital Signatures and you will know all about my further details and work, etc. Coming to point, I am here to inform all of you that take immediate actions on these issues are required for national interest and I need all the citizens of country to workout with unity on following issues because we all of us have been cheated in these elections of 2009. For explanation check these links and you will know the truth: EVM Tempering - Proved LIVE ON AIR on Sahara Samay and http://www.youtube.com/watch?v=EdretTflWEw Explanation on VHP/RSS/BJP/Sangh Parivar V/S Media V/S Misunderstandings About Sangh Parivar and it's related organizations: It's the time to come out on streets and stop India on it's place - Take immediate actions with full force for the cheating that has been done with you in the recent elections 2009. Millions of VHP members, millions of RSS members, millions of BJP members, millions of other party members are all together united now and I want to inform you that for your security and safety so many people will be there on streets. No one can dare to even touch you. Support this campaign led by millions of Indian citizens for the recent election cheating and frauds that were done with your voting rights this time. Just think that there are millions and millions of people in varying organizations and parties then how did such bogus results came out? Is it possible that so many supporters and collabrative parties are together with millions of citizens as their members and though such a difference and cheating with so many political parties, cheating with all 100 million citizens of India. Will you keep quite after knowing the truth of game played with your democratic rights? No don't sit ! everytime opportunity does not knock the door. (Join your parivaar ! Be Safe and Secure ! No one can dare to touch you or your family members if you are a part of this Sangh Parivaar) Forward this email to every member, every citizen of every state, every city and every rural as well as urban areas, and tell them also to keep forwarding this information to everyone and also take actions on their independant level as much as possible all across the nation with full force, every where in reach of each and every individual person all over the nation in each and every village, each and every family all over the nation. Let every person across the nation know how he/she has been cheated this time in the elections through EVM Tampering and modifying the programs. This was a LIVE ON AIR Evidence, so no one can even say that the video is wrong or has any problems or threats. I do my work with 100% perfection only and do not leave any option or chance for anyone to blame me anywhere. Media has always blamed RSS, VHP, all Sangh Parivaar Organizations as well as BJP for hindutva? Who the hell says that our organizations are only for hindu religions? Media self promotes themselves to increase their ratings and financial advertising revenues. I have evidence to prove this based on my research. Check these evidences: 1) Sikandar Bakht earlier, Mukhtar Abbas Naqvi and Shahnawaz Hussain are members of BJP from years. They are muslim and similar a large number of muslims are their in BJP. If the Sangh Parivar, VHP or BJP or any of their organizations are with hindu then why from years they are in BJP? Does media have answer to this? 2) There are the links of all small and big organizations linked with Sangh Parivar: http://www.sanghparivar.org/links Go through all of them and their members and executive level members. You will find many of them are muslim. Then can media answer that whether which is that day or time when Sangh Parivar has forcefully told those muslim members to leave the organization? We are believers of unity and peace. We don't accept terrorism, that doesn't mean that we don't accept Humanity? VHP or RSS or BJP or Sangh Parivar organization which never forcefully applies or imposed any particular religion related practice on any one across the nation. For example let's take my case. Why I am with VHP and RSS and BJP? Not for hindutva reasons. I am here because of unity of so many millions and millions of people. I have in my office all types of people of all types of religion. Similarly every individual who joins VHP or RSS has their own reasons why they are with RSS, BJP and VHP. But the idiot electronic media is falsefully promoting the wrong philosophy of RSS and VHP. The day when the mind if millions of VHP and RSS leaders and millions of their members is out of control. I promise that this wrong action of media will lead to end of their survival and will also lead to end of their company forever. They are falsefully showing continously wrong things about VHP, BJP and RSS philosophy. I have a lot of friends and colleagues in every religion. I never had any problems with anyone of them. Media has created the circumstances of hindutva related philosophy in between the public. No doubt they are promoting Hindutva, but there is also no doubt that they are not forcing hindutva to be applied on anyone. There is a difference when we talk both the things seperately. If any member of sangh parivar is hindu, then that member has rights of freedom to promote his religion. Similalry, if he is sikh he has the rights to promote sikhism. But either of them is not having rights nor sangh praivar's any organizations allows any member to forcefully accept hindutva in the way the Islamic Terrorism Organizations perform. This where and why I had to come out with this campaign to clarify everything and explain it in depth to the every citizen of our country and to every citizen of every nation all over world. We are a peaceful organization and accept all religions of all the nations. MEDIA APNI ROTI SEKNE KE LIYE 100 MILLION HINDUSTANI CITIZENS KO UNITED HONE SE ROKNE KI KOSHISH KAR RAHI HAI. KYON KI WOH JAANTE HAI KI AGAR HINDUSTAAN KI JANTA UNITED HO GAYI TO UNKI KYA HAALAT HOGI. MEDIA IS USING DIVIDE AND RULE POLICY AGAINST SANGH PARIVAR ORGANIZATIONS, BJP, VHP AND RSS AND THEIR MEMBERS AND MISGUIDING THE INDIAN CITIZENS. AAJ KI MEDIA KE LIYE UNKI KALAM, UNKA HATHIYAAR HO GAYA HAI. JIS KALAM KO EK ZAMAANE MEIN GANDHIJI JAISE LOG SAACHAI KE LIYE ISTEMAAL KARTE THE, US KALAM KO AAJKE MEDIA WALE APNI JEB GARAM KARNE KE LIYE KARTE HAI. YEH HI HAI SACHCHAY, AGAR MEDIA MEIN SUN NE KI TAAKAT HAI TO SUNO. TELEVISION PAR 10 BAAR YEH DIKHANE SE KI HUM SACHCHI KHABAR DIKHATE HAI, KOI MAHATMA GANDHI NAHIN BAN JATA. LEKIN MEIN BHI CHUP BAITHNE WALO MEIN SE NAHIN HOON. MAHATMA GANDHI NE ANGREJON SE DESH KO AAJAD KARVAYA THA, MEIN IS DESH KO CONGRESS SE AAJAD KARVA KE RAHUNGA. TAB TAK CHUP NAHIN BAITHUNGA, JAB TAK MERE MOOH MEIN JUBAAN HAI, AUR JAB TAK MERE HATH-PERON MEIN JAAN HAI, JAB TAK SAANSO KA TOOFAN HAI, JAB TAK MUJH MEIN SACHCHA IMAAN HAI ..... BJP, VHP and RSS never forces anyone and/or tells anyone to leave their religion and join Hinduism. We are those people who wants to live with freedom and let other live with freedom. But media always try to misguide the general public by making the news sensational and then creating an issue for them to increase ratings of their channels and fetch financial benefits from the advertisers. What can BJP, VHP and RSS do in that? BJP, RSS or any Sangh Parivar cannot force them to stop their news. Everyone has freedom of rights to say whatever they want. But anyway, the media will not be able to stop coming out the truth in front of everyone and that day will be the end of media agencies. Because when that day comes peoples will be mentally so much out of control that they will not be able to face the 100 million Indian Public. Media thinks that what we will show is the only truth, because they know that a common man cannot come out and start his own television channel to show the truth. But here media forgets one thing that now New media(Internet) Era has came and no one is any more depended on media alone. With the help of internet we can even target more then the people that media can target. So, if you are from any religion and believe the unity then do not worry and/or get misguided by any media agency. They want sensational news and will use you and throw you. This is the truth of media agencies in India. I have faced such troubles several times. Trust me ! I am telling the only truth and real fact in this email. This is first 4 minutes video. To see the complete video in which you can see how with the help of trojan horse program the EVM results were modified. The complete video splitted in 6 parts can be seen here: http://www.youtube.com/mohmaslam Please check this url for complete video. I have to post it in parts because on youtube only 10 minutes video is allowed, not more then 10 minutes. Whereas my complete live telecast is of 1 hour. So, I will post it in parts. I have sent the video to the company for dividing it into parts. My Target is millions and millions of people which I will achieve in one month and will work on following poetic grounds: Kuch Karke Humein Dikhana Hai, Bharat Ko Aage Lana Hai ! Rhode Patthar Jo Koi Bhi Aye, Un Sabko Hamein Mitana Hai ! Ae Bharat Ke Rehne Walon, Tumko Bhi Saath Nibhana Hai ! Kuch Karke Humein Dikhana Hai, Bharat Ko Aage Lana Hai. Aaj Agar, Nahin Kar Paye Kuch Toh, Jeevan Bhar Andhiyara Hai ! Lekin Agar Kar Paye Kuch Toh, Phir Yeh Desh Tumhara Hai ! Is Desh Ke Har Ek Dil Mein, Yeh Atma Vishwaas Jagana Hai ! Kuch Karke Humein Dikhana Hai, Bharat Ko Aage Lana Hai. Bum Chahe Ho Bandook Samne, Taan Ke Sina Kehna Hai ! Chalte Raho Badhte Chalo, Agar Duniya Ko Hilana Hai ! Chal Pade Ho Jis Raste Par Tum, Nahin Chod Ke Usko Jaana Hai ! Kuch Karke Humein Dikhana Hai, Bharat Ko Aage Lana Hai. (This is the mother who gave birth to our parivaar and we will all together respect our mother and save here from fraudsters and cheaters.) This is urgent and needs immediate action on the matter at a large level with full force. This is not a work for a particular one person or party or orgnanization. Instead this is for all of us and we will all be proud if due to our efforts re-election issue comes into action. So, it needs that every take out some time daily to keep forwarding this issue to every one all over the nation in each and every village and each and every area of each and every city all over India. Some of the supporters are required to record the CD of the video and submit them to people in areas where there are no news channels or internet facility such as rural and tribal areas. Use the production services to change the language in the areas where people do not understand hindi. Translate it to their mother toungue language and let them all feel from inside that how they have all been cheated in these recent 2009 elections. Because in the voting session during this LIVE on air telecast 90% people agreed that yes there was EVM tampering in this election due to which a huge change in modification of electronic voting machines(EVM) results was the reason of defeat of the national citizen's favourite candidates. Direct attack through cheating and fraud was done by winners with the feelings and emotions of 100 million citizens of India. Everyone should know now the truth face of fraud political people of Congress. It's the question of life for all of us and our benefits. So, hope you understand and do as much as possible to spread this message and explain it to every person all across the country. You can forward this email to all in your family, friends, organizations, colleagues, all employees, workers, etc. Paste the copy of this complete email article on internet, on forums, on blogs, everywhere possible for you. This is the way you can contribute to this unity project. Just post the copy as it is on article directories. If you need softwares to promote this email campaign, just mail me and I will send it to you with all explanations how to use it. In news sections, in comments, every where post the whole of the article. If there are places where images cannot be posted then just post the text contents. Thanking you all with a hope of co-operation and compromise from all national citizens across the country. This is not a war for a specific party or political person, instead this is my personal campaign for integration of unity amongst the national citizens without personal benefits for national interest, for public interest. Truth is bitter but always wins when worked out with unity. Sincerely Kalpesh Sharma Digital Signature of Achievements Freelance Security Consultant, Army Intelligence Ex-Technical Assistant to Honorable Chief Minister Narendra Modi Excellent Internet Marketing and Online Promotion Expert World's Biggest Penetration Tester (A World Record Holder) Online Technical Intelligence and Online Web Research Expert Private Cyber Crime Investigator for Some Media Agencies (Delhi Bomb Blast Case) Actor: Diploma in Acting from Honorable Anupam Kher's Institute Acting Portfolio and Profile: http://www.imj-online.com/kalpeshsharma Email: shrishanidev at gmail.com or cmtechnical at bsnl.in or armyintelli at reliancemail.net My Services Details: http://www.getafreelancer.com/users/417883.html Mobile: +91-9227435453 Preferred Way of Communication: Email and SMS Only Ahmedabad, India. My Permanent Village Address: Village Tholai, Tehsil: Jamva Ramgarh, District: Jaipur, Rajasthan. Member of the Honorable BJP, RSS, VHP and all the Sangh Pariwaar Organizations. About Sangh Pariwaar: Do you know, today millions and millions of people in India are members of Sangh Pariwaar. A very huge and big Organization. Think of it, that if you are a member of Sangh Pariwaar then how much secure you will be and your family, children will be. So, simply come and join Sangh Pariwaar and if you have any trouble just let me know. I am there for helping everyone for national interest without my personal benefits. We are not Congress who just works for their personal benefits only. See the power of unity and huge organizational structure here on http://www.sanghparivar.org and all it's sister concern party's organizations and unions of millions of government employees which are all connected with Sangh Pariwaar. Check it here which organizations are a part of Sangh Pariwaar: http://www.sanghparivar.org/links/view/all/1 and to join Sangh Pariwaar go on this link: http://www.sanghparivar.org/user/register (This is who will take care of us. I promise on behalf of him because I know he is a great person. I am proud that he is ruling on my state) -------------- next part -------------- An HTML attachment was scrubbed... URL: From current at pick.cz Tue Jul 28 18:52:42 2009 From: current at pick.cz (Seeney Mirao) Date: Tue, 28 Jul 2009 17:52:42 -0100 Subject: redoing Message-ID: <377926911061103231601079@pick.cz> oLvemaaking Tip for sex.www.5site5 .net From oleg at redhat.com Tue Jul 28 19:49:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 28 Jul 2009 21:49:05 +0200 Subject: [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction In-Reply-To: <20090728013917.120514213C@magilla.sf.frob.com> References: <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727233507.GA27478@redhat.com> <20090728003635.B08284213C@magilla.sf.frob.com> <20090728012534.GA31866@redhat.com> <20090728013917.120514213C@magilla.sf.frob.com> Message-ID: <20090728194905.GA11304@redhat.com> On 07/27, Roland McGrath wrote: > > > Ah. I forgot signals-tracehook_notify_jctl-change.patch is still pending in > > -mm. > > Perhaps we should just rejigger all these together into one new patch (or > two, whatever) before akpm submits any of them. > > > Or you can just merge these 2 patches, perhaps this would be better. > > As long as we have akpm drop/update the any conflicting ones, sure. OK, please find the patch below. changes: add the comment as you suggested. > > Confused, signals-tracehook_notify_jctl-change.patch already updated the > > comment? > > I was looking at the Linus tree, not the -mm tree (I always do). > If that prerequisite patch (or merged rejiggered patch or whatever) > updates the comments that is fine. Yes it does (and just in case, this patch is applied to your linux-2.6-utrace.git). > I was also just noticing the other > callers of tracehook_notify_jctl, which should all be rejiggered as makes > most sense for the locking change (maybe that pending patch already did that). Yes, it did. Questions: should I send the change in signal.c to Andrew right now? It can be applied separetely, it doesn't break utrace_report_jctl(). Should I send utrace part to Andrew too? This is not strictly needed. Oleg. --------------------------------------------------------------------- [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction do_signal_stop() can call utrace_report_jctl() before decrementing ->group_stop_count and setting TASK_STOPPED/SIGNAL_STOP_STOPPED. This allows to greatly simplify utrace_report_jctl() and avoid playing with group-stop bookkeeping twice. Signed-off-by: Oleg Nesterov ---- kernel/signal.c | 40 ++++++++++++++++++---------------------- kernel/utrace.c | 20 -------------------- 2 files changed, 18 insertions(+), 42 deletions(-) --- __UTRACE/kernel/signal.c~JCTL 2009-07-28 01:37:58.000000000 +0200 +++ __UTRACE/kernel/signal.c 2009-07-28 21:39:31.000000000 +0200 @@ -1682,16 +1682,9 @@ void ptrace_notify(int exit_code) static int do_signal_stop(int signr) { struct signal_struct *sig = current->signal; - int stop_count; int notify; - if (sig->group_stop_count > 0) { - /* - * There is a group stop in progress. We don't need to - * start another one. - */ - stop_count = --sig->group_stop_count; - } else { + if (!sig->group_stop_count) { struct task_struct *t; if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || @@ -1703,7 +1696,7 @@ static int do_signal_stop(int signr) */ sig->group_exit_code = signr; - stop_count = 0; + sig->group_stop_count = 1; for (t = next_thread(current); t != current; t = next_thread(t)) /* * Setting state to TASK_STOPPED for a group @@ -1712,25 +1705,28 @@ static int do_signal_stop(int signr) */ if (!(t->flags & PF_EXITING) && !task_is_stopped_or_traced(t)) { - stop_count++; + sig->group_stop_count++; signal_wake_up(t, 0); } - sig->group_stop_count = stop_count; } - - if (stop_count == 0) - sig->flags = SIGNAL_STOP_STOPPED; - current->exit_code = sig->group_exit_code; - __set_current_state(TASK_STOPPED); - /* * If there are no other threads in the group, or if there is - * a group stop in progress and we are the last to stop, - * report to the parent. When ptraced, every thread reports itself. + * a group stop in progress and we are the last to stop, report + * to the parent. When ptraced, every thread reports itself. */ - notify = tracehook_notify_jctl(stop_count == 0 ? CLD_STOPPED : 0, - CLD_STOPPED); - + notify = sig->group_stop_count == 1 ? CLD_STOPPED : 0; + notify = tracehook_notify_jctl(notify, CLD_STOPPED); + /* + * tracehook_notify_jctl() can drop and reacquire siglock, so + * we keep ->group_stop_count != 0 before the call. If SIGCONT + * or SIGKILL comes in between ->group_stop_count == 0. + */ + if (sig->group_stop_count) { + if (!--sig->group_stop_count) + sig->flags = SIGNAL_STOP_STOPPED; + current->exit_code = sig->group_exit_code; + __set_current_state(TASK_STOPPED); + } spin_unlock_irq(¤t->sighand->siglock); if (notify) { --- __UTRACE/kernel/utrace.c~JCTL 2009-07-28 20:55:01.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-28 20:56:32.000000000 +0200 @@ -1607,18 +1607,7 @@ void utrace_report_jctl(int notify, int struct task_struct *task = current; struct utrace *utrace = task_utrace_struct(task); INIT_REPORT(report); - bool stop = task_is_stopped(task); - /* - * We have to come out of TASK_STOPPED in case the event report - * hooks might block. Since we held the siglock throughout, it's - * as if we were never in TASK_STOPPED yet at all. - */ - if (stop) { - __set_current_state(TASK_RUNNING); - task->signal->flags &= ~SIGNAL_STOP_STOPPED; - ++task->signal->group_stop_count; - } spin_unlock_irq(&task->sighand->siglock); /* @@ -1647,16 +1636,7 @@ void utrace_report_jctl(int notify, int REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), report_jctl, what, notify); - /* - * Retake the lock, and go back into TASK_STOPPED - * unless the stop was just cleared. - */ spin_lock_irq(&task->sighand->siglock); - if (stop && task->signal->group_stop_count > 0) { - __set_current_state(TASK_STOPPED); - if (--task->signal->group_stop_count == 0) - task->signal->flags |= SIGNAL_STOP_STOPPED; - } } /* From oleg at redhat.com Tue Jul 28 20:07:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 28 Jul 2009 22:07:56 +0200 Subject: [PATCH] utrace_wakeup: take ->group_stop_count into account Message-ID: <20090728200756.GA13831@redhat.com> utrace_wakeup() should take ->group_stop_count into account, we should not wake up if group stop is in progress. Also, kill "sighand" variable. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~WAKEUP_CHECK_GSC 2009-07-28 20:56:32.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-28 21:55:43.000000000 +0200 @@ -807,17 +807,16 @@ static bool utrace_do_stop(struct task_s */ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) { - struct sighand_struct *sighand; unsigned long irqflags; utrace->stopped = 0; - sighand = lock_task_sighand(target, &irqflags); - if (unlikely(!sighand)) + if (!lock_task_sighand(target, &irqflags)) return; if (likely(task_is_stopped_or_traced(target))) { - if (target->signal->flags & SIGNAL_STOP_STOPPED) + if (target->signal->flags & SIGNAL_STOP_STOPPED || + target->signal->group_stop_count) target->state = TASK_STOPPED; else wake_up_state(target, __TASK_STOPPED | __TASK_TRACED); From oleg at redhat.com Tue Jul 28 20:27:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 28 Jul 2009 22:27:41 +0200 Subject: [PATCH] utrace_stop: don't forget about SIGNAL_STOP_STOPPED Message-ID: <20090728202741.GA15857@redhat.com> utrace_stop() decrements ->group_stop_count but doesn't set SIGNAL_STOP_STOPPED if we are the last thread. This breaks utrace_wakeup() logic. Perhaps we need more changes here, but I think this one is most important. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~UTRACE_STOP_SSS 2009-07-28 21:55:43.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-28 22:12:44.000000000 +0200 @@ -416,8 +416,9 @@ static bool utrace_stop(struct task_stru * If there is a group stop in progress, * we must participate in the bookkeeping. */ - if (task->signal->group_stop_count > 0) - --task->signal->group_stop_count; + if (unlikely(task->signal->group_stop_count) && + !--task->signal->group_stop_count) + task->signal->flags = SIGNAL_STOP_STOPPED; spin_unlock_irq(&task->sighand->siglock); spin_unlock(&utrace->lock); From roland at redhat.com Tue Jul 28 21:17:05 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 28 Jul 2009 14:17:05 -0700 (PDT) Subject: [PATCH] utrace_stop: don't forget about SIGNAL_STOP_STOPPED In-Reply-To: Oleg Nesterov's message of Tuesday, 28 July 2009 22:27:41 +0200 <20090728202741.GA15857@redhat.com> References: <20090728202741.GA15857@redhat.com> Message-ID: <20090728211705.9E3EB4213C@magilla.sf.frob.com> > Perhaps we need more changes here, but I think this one is most important. Agreed, we definitely do. For the generic case it needs to complete what do_signal_stop would do. That is, do_notify_parent_cldstop and maybe also: current->exit_code = sig->group_exit_code; Though it might be now that it obsolete wrt your newer exit.c changes, and either nothing uses that ->exit_code or only ptrace does. However, we want to suppress that do_notify_parent_cldstop for ptrace, where its ->report_jctl has already arranged to deal with that. So this would have whatever the same new "inhibit-wait" check is we use inside tracehook_notify_jctl for ptrace, but we haven't decied on that yet. Hmm. Perhaps it can just call tracehook_notify_jctl here. Thanks, Roland From roland at redhat.com Tue Jul 28 22:14:21 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 28 Jul 2009 15:14:21 -0700 (PDT) Subject: [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction In-Reply-To: Oleg Nesterov's message of Tuesday, 28 July 2009 21:49:05 +0200 <20090728194905.GA11304@redhat.com> References: <20090721205801.9FDDA64@magilla.sf.frob.com> <20090722161331.GA7305@redhat.com> <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727233507.GA27478@redhat.com> <20090728003635.B08284213C@magilla.sf.frob.com> <20090728012534.GA31866@redhat.com> <20090728013917.120514213C@magilla.sf.frob.com> <20090728194905.GA11304@redhat.com> Message-ID: <20090728221422.045CA4213C@magilla.sf.frob.com> > Questions: should I send the change in signal.c to Andrew right now? > It can be applied separetely, it doesn't break utrace_report_jctl(). Yes, send it now. It might be best just to send a replacement for signals-tracehook_notify_jctl-change.patch that rolls this in. I wouldn't mention particular utrace code in its log message. Just something like the old log paragraph: Tracing needs the siglock here, held from the time TASK_STOPPED was set, to avoid potential SIGCONT races if it wants to allow any blocking in its tracing hooks. adjusted appropriately, perhaps: Tracing wants to be able to drop and reacquire the siglock here, before TASK_STOPPED is set, to avoid potential SIGCONT races if it wants to allow any blocking in its tracing hooks. Thanks, Roland From oleg at redhat.com Tue Jul 28 22:20:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 00:20:43 +0200 Subject: [PATCH 0/4] utrace->stopped fixes/cleanups Message-ID: <20090728222043.GA26525@redhat.com> If you agree with these patches, should I send the first one to Andrew? 4/4 doesn't really depend on 1-3, except the comment change. Oleg. From oleg at redhat.com Tue Jul 28 22:20:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 00:20:46 +0200 Subject: [PATCH 1/4] introduce tracehook_finish_jctl() helper Message-ID: <20090728222046.GA26529@redhat.com> Introduce the empty inline tracehook_finish_jctl() helper called by do_signal_stop() after wakeup. Currently we lack the ability to report this state change. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 9 +++++++++ kernel/signal.c | 2 ++ 2 files changed, 11 insertions(+) --- __UTRACE/include/linux/tracehook.h~JCTL_1_TRACEHOOK 2009-07-28 22:59:03.000000000 +0200 +++ __UTRACE/include/linux/tracehook.h 2009-07-28 22:59:31.000000000 +0200 @@ -521,6 +521,15 @@ static inline int tracehook_notify_jctl( return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; } +/** + * tracehook_finish_jctl - report about return from job control stop + * + * This is called by do_signal_stop() after wakeup. + */ +static inline void tracehook_finish_jctl(void) +{ +} + #define DEATH_REAP -1 #define DEATH_DELAYED_GROUP_LEADER -2 --- __UTRACE/kernel/signal.c~JCTL_1_TRACEHOOK 2009-07-28 21:39:31.000000000 +0200 +++ __UTRACE/kernel/signal.c 2009-07-28 23:02:00.000000000 +0200 @@ -1738,6 +1738,8 @@ static int do_signal_stop(int signr) do { schedule(); } while (try_to_freeze()); + + tracehook_finish_jctl(); /* * Now we don't run again until continued. */ From oleg at redhat.com Tue Jul 28 22:20:48 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 00:20:48 +0200 Subject: [PATCH 2/4] use tracehook_finish_jctl() to clear ->stopped Message-ID: <20090728222048.GA26536@redhat.com> Use tracehook_finish_jctl() to clear utrace->stopped. From now we shouldn't worry about ->stopped "leaking" after jctl stop. Signed-off-by: Oleg Nesterov --- include/linux/utrace.h | 2 ++ include/linux/tracehook.h | 2 ++ kernel/utrace.c | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+) --- __UTRACE/include/linux/utrace.h~JCTL_2_CLEAR_STOPPED 2009-04-21 22:43:29.000000000 +0200 +++ __UTRACE/include/linux/utrace.h 2009-07-28 23:27:14.000000000 +0200 @@ -109,6 +109,8 @@ void utrace_report_death(struct task_str __attribute__((weak)); void utrace_report_jctl(int notify, int type) __attribute__((weak)); +void utrace_finish_jctl(void) + __attribute__((weak)); void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, struct pt_regs *regs) __attribute__((weak)); --- __UTRACE/include/linux/tracehook.h~JCTL_2_CLEAR_STOPPED 2009-07-28 22:59:31.000000000 +0200 +++ __UTRACE/include/linux/tracehook.h 2009-07-28 23:28:47.000000000 +0200 @@ -528,6 +528,8 @@ static inline int tracehook_notify_jctl( */ static inline void tracehook_finish_jctl(void) { + if (task_utrace_flags(current)) + utrace_finish_jctl(); } #define DEATH_REAP -1 --- __UTRACE/kernel/utrace.c~JCTL_2_CLEAR_STOPPED 2009-07-28 23:32:58.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-28 23:41:54.000000000 +0200 @@ -1640,6 +1640,24 @@ void utrace_report_jctl(int notify, int } /* + * Called without locks. + */ +void utrace_finish_jctl(void) +{ + struct utrace *utrace = task_utrace_struct(current); + /* + * While in TASK_STOPPED, we can be considered safely + * stopped by utrace_do_stop(). Clear ->stopped if we + * were woken by signal. + */ + if (utrace->stopped) { + spin_lock(&utrace->lock); + utrace->stopped = false; + spin_unlock(&utrace->lock); + } +} + +/* * Called iff UTRACE_EVENT(EXIT) flag is set. */ void utrace_report_exit(long *exit_code) From oleg at redhat.com Tue Jul 28 22:20:50 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 00:20:50 +0200 Subject: [PATCH 3/4] utrace_report_jctl/utrace_get_signal: do not play with ->stopped Message-ID: <20090728222050.GA26539@redhat.com> Now that we always clear ->stopped in utrace_finish_jctl(), we can cleanup utrace_report_jctl() and utrace_get_signal(), they do not need to worry about ->stopped == T any longer. Note that the change in utrace_report_jctl() removes start_report()'s work too. Contrary to what the comment says, REPORT() does call start_report(). >From now the rules for ->stopped are very simple: - it is set by utrace_stop() or utrace_do_stop() - it is clered by utrace_wakeup(), or if the tracee is woken by signal we clear it in finish_utrace_stop() or utrace_finish_jctl() Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) --- __UTRACE/kernel/utrace.c~JCTL_3_CLEANUP 2009-07-28 23:41:54.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-28 23:59:28.000000000 +0200 @@ -1610,29 +1610,6 @@ void utrace_report_jctl(int notify, int spin_unlock_irq(&task->sighand->siglock); - /* - * We get here with CLD_STOPPED when we've just entered - * TASK_STOPPED, or with CLD_CONTINUED when we've just come - * out but not yet been through utrace_get_signal() again. - * - * While in TASK_STOPPED, we can be considered safely - * stopped by utrace_do_stop() and detached asynchronously. - * If we woke up and checked task->utrace_flags before that - * was finished, we might be here with utrace already - * removed or in the middle of being removed. - * - * If we are indeed attached, then make sure we are no - * longer considered stopped while we run callbacks. - */ - spin_lock(&utrace->lock); - utrace->stopped = 0; - /* - * Do start_report()'s work too since we already have the lock anyway. - */ - utrace->report = 0; - splice_attaching(utrace); - spin_unlock(&utrace->lock); - REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), report_jctl, what, notify); @@ -1925,8 +1902,6 @@ int utrace_get_signal(struct task_struct * interrupt path, so clear the flags asking for those. */ utrace->interrupt = utrace->report = utrace->signal_handler = 0; - utrace->stopped = 0; - /* * Make sure signal_pending() only returns true * if there are real signals pending. @@ -1954,22 +1929,13 @@ int utrace_get_signal(struct task_struct event = 0; ka = NULL; memset(return_ka, 0, sizeof *return_ka); - } else if ((task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) == 0 && - !utrace->stopped) { + } else if ((task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) == 0) { /* * If no engine is interested in intercepting signals, * let the caller just dequeue them normally. */ return 0; } else { - if (unlikely(utrace->stopped)) { - spin_unlock_irq(&task->sighand->siglock); - spin_lock(&utrace->lock); - utrace->stopped = 0; - spin_unlock(&utrace->lock); - spin_lock_irq(&task->sighand->siglock); - } - /* * Steal the next signal so we can let tracing engines * examine it. From the signal number and sigaction, From oleg at redhat.com Tue Jul 28 22:20:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 00:20:53 +0200 Subject: [PATCH 4/4] utrace_do_stop: s/STOPPED/TRACED/ to protect against SIGCONT Message-ID: <20090728222053.GA26542@redhat.com> utrace_do_stop() sets utrace->stopped but leaves the tracee in TASK_STOPPED state. This means SIGCONT can wake up the tracee and fool the tracer. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- __UTRACE/kernel/utrace.c~JCTL_4_STOP_TRACED 2009-07-28 23:59:28.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-29 00:14:42.000000000 +0200 @@ -788,8 +788,9 @@ static bool utrace_do_stop(struct task_s } else if (task_is_stopped(target)) { /* * Stopped is considered quiescent; when it wakes up, it will - * go through utrace_get_signal() before doing anything else. + * go through utrace_finish_jctl() before doing anything else. */ + __set_task_state(target, TASK_TRACED); utrace->stopped = stopped = true; } else if (!utrace->report && !utrace->interrupt) { utrace->report = 1; From roland at redhat.com Tue Jul 28 22:50:57 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 28 Jul 2009 15:50:57 -0700 (PDT) Subject: [PATCH 1/4] introduce tracehook_finish_jctl() helper In-Reply-To: Oleg Nesterov's message of Wednesday, 29 July 2009 00:20:46 +0200 <20090728222046.GA26529@redhat.com> References: <20090728222046.GA26529@redhat.com> Message-ID: <20090728225057.407184C721@magilla.sf.frob.com> > Introduce the empty inline tracehook_finish_jctl() helper called by > do_signal_stop() after wakeup. You could possibly roll this into the tracehook_notify_jctl rework too. Or send it upstream separately, either way. > +/** > + * tracehook_finish_jctl - report about return from job control stop > + * > + * This is called by do_signal_stop() after wakeup. + * Called without locks. Just for consistency/completeness of tracehook.h kerneldoc. > } while (try_to_freeze()); > + > + tracehook_finish_jctl(); > /* > * Now we don't run again until continued. > */ Move the hook after this comment, since the comment is a "stopped now" comment and the hook is the "continued again" hook. Thanks, Roland From roland at redhat.com Tue Jul 28 22:53:50 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 28 Jul 2009 15:53:50 -0700 (PDT) Subject: [PATCH 2/4] use tracehook_finish_jctl() to clear ->stopped In-Reply-To: Oleg Nesterov's message of Wednesday, 29 July 2009 00:20:48 +0200 <20090728222048.GA26536@redhat.com> References: <20090728222048.GA26536@redhat.com> Message-ID: <20090728225350.5B5E04C721@magilla.sf.frob.com> > + * While in TASK_STOPPED, we can be considered safely > + * stopped by utrace_do_stop(). Clear ->stopped if we > + * were woken by signal. s/signal/SIGKILL/, no? It's not really "while in TASK_STOPPED" any more, it's that utrace_do_stop could have changed TASK_STOPPED to TASK_TRACED. Then the only case is that we wake up now because of SIGKILL. If utrace_wakeup woke us, it would have cleared ->stopped itself. Thanks, Roland From roland at redhat.com Tue Jul 28 22:56:56 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 28 Jul 2009 15:56:56 -0700 (PDT) Subject: [PATCH 4/4] utrace_do_stop: s/STOPPED/TRACED/ to protect against SIGCONT In-Reply-To: Oleg Nesterov's message of Wednesday, 29 July 2009 00:20:53 +0200 <20090728222053.GA26542@redhat.com> References: <20090728222053.GA26542@redhat.com> Message-ID: <20090728225656.D79824C721@magilla.sf.frob.com> > utrace_do_stop() sets utrace->stopped but leaves the tracee in TASK_STOPPED > state. This means SIGCONT can wake up the tracee and fool the tracer. IMHO this one belongs before 2/4 and 3/4 and all the comments changed to reflect that SIGKILL is the only case. But the incremental order really doesn't matter for the utrace part, we will just merge these all and eventually generate fresh utrace patches from scratch for upstream submission, not incremental ones. Thanks, Roland From oleg at redhat.com Tue Jul 28 23:13:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 01:13:10 +0200 Subject: [PATCH 1/4] introduce tracehook_finish_jctl() helper In-Reply-To: <20090728225057.407184C721@magilla.sf.frob.com> References: <20090728222046.GA26529@redhat.com> <20090728225057.407184C721@magilla.sf.frob.com> Message-ID: <20090728231310.GA28339@redhat.com> On 07/28, Roland McGrath wrote: > > > Introduce the empty inline tracehook_finish_jctl() helper called by > > do_signal_stop() after wakeup. > > You could possibly roll this into the tracehook_notify_jctl rework too. > Or send it upstream separately, either way. I'd prefer to send it separately, just to avoid the "how this hook is connected to subtle changes in do_signal_stop" questions/discussion. > > +/** > > + * tracehook_finish_jctl - report about return from job control stop > > + * > > + * This is called by do_signal_stop() after wakeup. > > + * Called without locks. > > Just for consistency/completeness of tracehook.h kerneldoc. OK, will re-send. > > } while (try_to_freeze()); > > + > > + tracehook_finish_jctl(); > > /* > > * Now we don't run again until continued. > > */ > > Move the hook after this comment, since the comment is a "stopped now" > comment and the hook is the "continued again" hook. Hmm... shouldn't we move this comment above schedule() ? And, perhaps, /* Now we don't run again until continued or killed */ ? Oleg. From oleg at redhat.com Tue Jul 28 23:19:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 01:19:31 +0200 Subject: [PATCH 2/4] use tracehook_finish_jctl() to clear ->stopped In-Reply-To: <20090728225350.5B5E04C721@magilla.sf.frob.com> References: <20090728222048.GA26536@redhat.com> <20090728225350.5B5E04C721@magilla.sf.frob.com> Message-ID: <20090728231931.GB28339@redhat.com> On 07/28, Roland McGrath wrote: > > > + * While in TASK_STOPPED, we can be considered safely > > + * stopped by utrace_do_stop(). Clear ->stopped if we > > + * were woken by signal. > > s/signal/SIGKILL/, no? It's not really "while in TASK_STOPPED" any more, > it's that utrace_do_stop could have changed TASK_STOPPED to TASK_TRACED. > Then the only case is that we wake up now because of SIGKILL. Yes sure, but only after we change utrace_do_stop() to set TASK_TRACED. OK, I'll do s/signal/SIGKILL/ in the comment. Actually I was going to do this in 4/4 but forgot. > If utrace_wakeup woke us, it would have cleared ->stopped itself. Yes, that is why the comment says "woken by signal". Oleg. From oleg at redhat.com Tue Jul 28 23:21:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 01:21:30 +0200 Subject: [PATCH 4/4] utrace_do_stop: s/STOPPED/TRACED/ to protect against SIGCONT In-Reply-To: <20090728225656.D79824C721@magilla.sf.frob.com> References: <20090728222053.GA26542@redhat.com> <20090728225656.D79824C721@magilla.sf.frob.com> Message-ID: <20090728232130.GC28339@redhat.com> On 07/28, Roland McGrath wrote: > > > utrace_do_stop() sets utrace->stopped but leaves the tracee in TASK_STOPPED > > state. This means SIGCONT can wake up the tracee and fool the tracer. > > IMHO this one belongs before 2/4 and 3/4 and all the comments changed to > reflect that SIGKILL is the only case. But the incremental order really > doesn't matter for the utrace part, we will just merge these all and > eventually generate fresh utrace patches from scratch for upstream > submission, not incremental ones. Yes, agreed. OK, I'll send the first patch upstream, then I re-send 2-4 with updated comments to you. Oleg. From roland at redhat.com Tue Jul 28 23:29:21 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 28 Jul 2009 16:29:21 -0700 (PDT) Subject: [PATCH 1/4] introduce tracehook_finish_jctl() helper In-Reply-To: Oleg Nesterov's message of Wednesday, 29 July 2009 01:13:10 +0200 <20090728231310.GA28339@redhat.com> References: <20090728222046.GA26529@redhat.com> <20090728225057.407184C721@magilla.sf.frob.com> <20090728231310.GA28339@redhat.com> Message-ID: <20090728232921.A910C4C721@magilla.sf.frob.com> > I'd prefer to send it separately, just to avoid the "how this hook is > connected to subtle changes in do_signal_stop" questions/discussion. Fine, it's up to you and Andrew. > Hmm... shouldn't we move this comment above schedule() ? And, perhaps, > > /* Now we don't run again until continued or killed */ > > ? Sure, it's fine to rewrite it. You might say "woken by SIGCONT or SIGKILL" to make it a little more explicit what you mean. Thanks, Roland From roland at redhat.com Tue Jul 28 23:31:32 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 28 Jul 2009 16:31:32 -0700 (PDT) Subject: [PATCH 4/4] utrace_do_stop: s/STOPPED/TRACED/ to protect against SIGCONT In-Reply-To: Oleg Nesterov's message of Wednesday, 29 July 2009 01:21:30 +0200 <20090728232130.GC28339@redhat.com> References: <20090728222053.GA26542@redhat.com> <20090728225656.D79824C721@magilla.sf.frob.com> <20090728232130.GC28339@redhat.com> Message-ID: <20090728233132.A75024C721@magilla.sf.frob.com> > OK, I'll send the first patch upstream, then I re-send 2-4 with updated > comments to you. Ok, good. When I get those I'll merge those upstream-bound ones into the tracehook git branch (now just signals-tracehook_notify_jctl-change.patch) and merge the utrace changes into the utrace branch. Thanks, Roland From oleg at redhat.com Tue Jul 28 23:50:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 01:50:46 +0200 Subject: [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction In-Reply-To: <20090728221422.045CA4213C@magilla.sf.frob.com> References: <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727233507.GA27478@redhat.com> <20090728003635.B08284213C@magilla.sf.frob.com> <20090728012534.GA31866@redhat.com> <20090728013917.120514213C@magilla.sf.frob.com> <20090728194905.GA11304@redhat.com> <20090728221422.045CA4213C@magilla.sf.frob.com> Message-ID: <20090728235046.GD28339@redhat.com> On 07/28, Roland McGrath wrote: > > > Questions: should I send the change in signal.c to Andrew right now? > > It can be applied separetely, it doesn't break utrace_report_jctl(). > > Yes, send it now. OK, will do > It might be best just to send a replacement > for signals-tracehook_notify_jctl-change.patch that rolls this in. Oh. I am looking at signals-tracehook_notify_jctl-change.patch. It is not trivial but doesn't really change do_signal_stop() (except it folds finish_stop() into). Roland, I'd prefer to send this change separately. Otherwise it will be really hard to review the unified patch. > I wouldn't mention particular utrace code in its log message. Yes, yes, sure. > Just something like the old log paragraph: > > Tracing needs the siglock here, held from the time TASK_STOPPED was set, > to avoid potential SIGCONT races if it wants to allow any blocking in its > tracing hooks. > > adjusted appropriately, perhaps: > > Tracing wants to be able to drop and reacquire the siglock here, > before TASK_STOPPED is set, to avoid potential SIGCONT races if it > wants to allow any blocking in its tracing hooks. OK, thanks. Oleg. From oleg at redhat.com Wed Jul 29 00:15:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 02:15:40 +0200 Subject: [PATCH] tracehooks: remove death_cookie from exit_notify() path In-Reply-To: <20090728233132.A75024C721@magilla.sf.frob.com> References: <20090728222053.GA26542@redhat.com> <20090728225656.D79824C721@magilla.sf.frob.com> <20090728232130.GC28339@redhat.com> <20090728233132.A75024C721@magilla.sf.frob.com> Message-ID: <20090729001540.GA664@redhat.com> On 07/28, Roland McGrath wrote: > > > OK, I'll send the first patch upstream, then I re-send 2-4 with updated > > comments to you. > > Ok, good. When I get those I'll merge those upstream-bound ones into the > tracehook git branch (now just signals-tracehook_notify_jctl-change.patch) > and merge the utrace changes into the utrace branch. Since we are going to send some tracehook changes upstream, how about the patch below as well? I think it is very unlikely we will need death_cookie in the near future, and it is always nice to simplify the code. Oleg. -------------------------------------------------------------------------- [PATCH] tracehooks: remove death_cookie from exit_notify() path Remove "void *death_cookie" from exit_notify() pathes, it is not really used. --- __UTRACE/include/linux/utrace.h~KILL_COOKIE 2009-07-28 23:27:14.000000000 +0200 +++ __UTRACE/include/linux/utrace.h 2009-07-29 02:05:07.000000000 +0200 @@ -105,7 +105,7 @@ void utrace_finish_vfork(struct task_str __attribute__((weak)); void utrace_report_exit(long *exit_code) __attribute__((weak)); -void utrace_report_death(struct task_struct *, struct utrace *, bool, int) +void utrace_report_death(struct task_struct *, bool, int) __attribute__((weak)); void utrace_report_jctl(int notify, int type) __attribute__((weak)); --- __UTRACE/include/linux/tracehook.h~KILL_COOKIE 2009-07-28 23:28:47.000000000 +0200 +++ __UTRACE/include/linux/tracehook.h 2009-07-29 02:04:42.000000000 +0200 @@ -538,7 +538,6 @@ static inline void tracehook_finish_jctl /** * tracehook_notify_death - task is dead, ready to notify parent * @task: @current task now exiting - * @death_cookie: value to pass to tracehook_report_death() * @group_dead: nonzero if this was the last thread in the group to die * * A return value >= 0 means call do_notify_parent() with that signal @@ -550,10 +549,8 @@ static inline void tracehook_finish_jctl * Called with write_lock_irq(&tasklist_lock) held. */ static inline int tracehook_notify_death(struct task_struct *task, - void **death_cookie, int group_dead) + int group_dead) { - *death_cookie = task_utrace_struct(task); - if (task_detached(task)) return task->ptrace ? SIGCHLD : DEATH_REAP; @@ -572,14 +569,12 @@ static inline int tracehook_notify_death * tracehook_report_death - task is dead and ready to be reaped * @task: @current task now exiting * @signal: return value from tracheook_notify_death() - * @death_cookie: value passed back from tracehook_notify_death() * @group_dead: nonzero if this was the last thread in the group to die * * Thread has just become a zombie or is about to self-reap. If positive, * @signal is the signal number just sent to the parent (usually %SIGCHLD). * If @signal is %DEATH_REAP, this thread will self-reap. If @signal is * %DEATH_DELAYED_GROUP_LEADER, this is a delayed_group_leader() zombie. - * The @death_cookie was passed back by tracehook_notify_death(). * * If normal reaping is not inhibited, @task->exit_state might be changing * in parallel. @@ -587,8 +582,7 @@ static inline int tracehook_notify_death * Called without locks. */ static inline void tracehook_report_death(struct task_struct *task, - int signal, void *death_cookie, - int group_dead) + int signal, int group_dead) { /* * This barrier ensures that our caller's setting of @@ -603,7 +597,7 @@ static inline void tracehook_report_deat */ smp_mb(); if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) - utrace_report_death(task, death_cookie, group_dead, signal); + utrace_report_death(task, group_dead, signal); } #ifdef TIF_NOTIFY_RESUME --- __UTRACE/kernel/exit.c~KILL_COOKIE 2009-07-13 17:44:27.000000000 +0200 +++ __UTRACE/kernel/exit.c 2009-07-29 02:02:47.000000000 +0200 @@ -803,7 +803,6 @@ static void forget_original_parent(struc static void exit_notify(struct task_struct *tsk, int group_dead) { int signal; - void *cookie; /* * This does two things: @@ -839,7 +838,7 @@ static void exit_notify(struct task_stru tsk->self_exec_id != tsk->parent_exec_id)) tsk->exit_signal = SIGCHLD; - signal = tracehook_notify_death(tsk, &cookie, group_dead); + signal = tracehook_notify_death(tsk, group_dead); if (signal >= 0) signal = do_notify_parent(tsk, signal); @@ -853,7 +852,7 @@ static void exit_notify(struct task_stru write_unlock_irq(&tasklist_lock); - tracehook_report_death(tsk, signal, cookie, group_dead); + tracehook_report_death(tsk, signal, group_dead); /* If the process is dead, release it - nobody will wait for it */ if (signal == DEATH_REAP) --- __UTRACE/kernel/utrace.c~KILL_COOKIE 2009-07-29 00:14:42.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-29 02:06:20.000000000 +0200 @@ -1659,9 +1659,9 @@ void utrace_report_exit(long *exit_code) * For this reason, utrace_release_task checks for the event bits that get * us here, and delays its cleanup for us to do. */ -void utrace_report_death(struct task_struct *task, struct utrace *utrace, - bool group_dead, int signal) +void utrace_report_death(struct task_struct *task, bool group_dead, int signal) { + struct utrace *utrace = task_utrace_struct(task); INIT_REPORT(report); BUG_ON(!task->exit_state); From reservaciones at laspalmasclub.com Wed Jul 29 00:30:04 2009 From: reservaciones at laspalmasclub.com (Las Palmas By The Sea) Date: Tue, 28 Jul 2009 20:30:04 -0400 Subject: Summer spectacular in Vallarta Message-ID: <48b977fc90abb103be721067eba685e5@www.vallarta-paradise.com> An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Jul 29 00:40:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 02:40:57 +0200 Subject: [PATCH] tracehooks: remove death_cookie from exit_notify() path In-Reply-To: <20090729001540.GA664@redhat.com> References: <20090728222053.GA26542@redhat.com> <20090728225656.D79824C721@magilla.sf.frob.com> <20090728232130.GC28339@redhat.com> <20090728233132.A75024C721@magilla.sf.frob.com> <20090729001540.GA664@redhat.com> Message-ID: <20090729004057.GA1974@redhat.com> Damn. Please ignore. Somehow I missed the fact that the patch below changes both tracehooks and utrace.c, it is not possible to send the tracehook part to Andrew. But I think it would be really nice to do this cleanup before sending the next version of utrace. Oleg. On 07/29, Oleg Nesterov wrote: > > On 07/28, Roland McGrath wrote: > > > > > OK, I'll send the first patch upstream, then I re-send 2-4 with updated > > > comments to you. > > > > Ok, good. When I get those I'll merge those upstream-bound ones into the > > tracehook git branch (now just signals-tracehook_notify_jctl-change.patch) > > and merge the utrace changes into the utrace branch. > > Since we are going to send some tracehook changes upstream, how about the > patch below as well? > > I think it is very unlikely we will need death_cookie in the near future, > and it is always nice to simplify the code. > > Oleg. > > -------------------------------------------------------------------------- > [PATCH] tracehooks: remove death_cookie from exit_notify() path > > Remove "void *death_cookie" from exit_notify() pathes, it is not really > used. > > > --- __UTRACE/include/linux/utrace.h~KILL_COOKIE 2009-07-28 23:27:14.000000000 +0200 > +++ __UTRACE/include/linux/utrace.h 2009-07-29 02:05:07.000000000 +0200 > @@ -105,7 +105,7 @@ void utrace_finish_vfork(struct task_str > __attribute__((weak)); > void utrace_report_exit(long *exit_code) > __attribute__((weak)); > -void utrace_report_death(struct task_struct *, struct utrace *, bool, int) > +void utrace_report_death(struct task_struct *, bool, int) > __attribute__((weak)); > void utrace_report_jctl(int notify, int type) > __attribute__((weak)); > --- __UTRACE/include/linux/tracehook.h~KILL_COOKIE 2009-07-28 23:28:47.000000000 +0200 > +++ __UTRACE/include/linux/tracehook.h 2009-07-29 02:04:42.000000000 +0200 > @@ -538,7 +538,6 @@ static inline void tracehook_finish_jctl > /** > * tracehook_notify_death - task is dead, ready to notify parent > * @task: @current task now exiting > - * @death_cookie: value to pass to tracehook_report_death() > * @group_dead: nonzero if this was the last thread in the group to die > * > * A return value >= 0 means call do_notify_parent() with that signal > @@ -550,10 +549,8 @@ static inline void tracehook_finish_jctl > * Called with write_lock_irq(&tasklist_lock) held. > */ > static inline int tracehook_notify_death(struct task_struct *task, > - void **death_cookie, int group_dead) > + int group_dead) > { > - *death_cookie = task_utrace_struct(task); > - > if (task_detached(task)) > return task->ptrace ? SIGCHLD : DEATH_REAP; > > @@ -572,14 +569,12 @@ static inline int tracehook_notify_death > * tracehook_report_death - task is dead and ready to be reaped > * @task: @current task now exiting > * @signal: return value from tracheook_notify_death() > - * @death_cookie: value passed back from tracehook_notify_death() > * @group_dead: nonzero if this was the last thread in the group to die > * > * Thread has just become a zombie or is about to self-reap. If positive, > * @signal is the signal number just sent to the parent (usually %SIGCHLD). > * If @signal is %DEATH_REAP, this thread will self-reap. If @signal is > * %DEATH_DELAYED_GROUP_LEADER, this is a delayed_group_leader() zombie. > - * The @death_cookie was passed back by tracehook_notify_death(). > * > * If normal reaping is not inhibited, @task->exit_state might be changing > * in parallel. > @@ -587,8 +582,7 @@ static inline int tracehook_notify_death > * Called without locks. > */ > static inline void tracehook_report_death(struct task_struct *task, > - int signal, void *death_cookie, > - int group_dead) > + int signal, int group_dead) > { > /* > * This barrier ensures that our caller's setting of > @@ -603,7 +597,7 @@ static inline void tracehook_report_deat > */ > smp_mb(); > if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) > - utrace_report_death(task, death_cookie, group_dead, signal); > + utrace_report_death(task, group_dead, signal); > } > > #ifdef TIF_NOTIFY_RESUME > --- __UTRACE/kernel/exit.c~KILL_COOKIE 2009-07-13 17:44:27.000000000 +0200 > +++ __UTRACE/kernel/exit.c 2009-07-29 02:02:47.000000000 +0200 > @@ -803,7 +803,6 @@ static void forget_original_parent(struc > static void exit_notify(struct task_struct *tsk, int group_dead) > { > int signal; > - void *cookie; > > /* > * This does two things: > @@ -839,7 +838,7 @@ static void exit_notify(struct task_stru > tsk->self_exec_id != tsk->parent_exec_id)) > tsk->exit_signal = SIGCHLD; > > - signal = tracehook_notify_death(tsk, &cookie, group_dead); > + signal = tracehook_notify_death(tsk, group_dead); > if (signal >= 0) > signal = do_notify_parent(tsk, signal); > > @@ -853,7 +852,7 @@ static void exit_notify(struct task_stru > > write_unlock_irq(&tasklist_lock); > > - tracehook_report_death(tsk, signal, cookie, group_dead); > + tracehook_report_death(tsk, signal, group_dead); > > /* If the process is dead, release it - nobody will wait for it */ > if (signal == DEATH_REAP) > --- __UTRACE/kernel/utrace.c~KILL_COOKIE 2009-07-29 00:14:42.000000000 +0200 > +++ __UTRACE/kernel/utrace.c 2009-07-29 02:06:20.000000000 +0200 > @@ -1659,9 +1659,9 @@ void utrace_report_exit(long *exit_code) > * For this reason, utrace_release_task checks for the event bits that get > * us here, and delays its cleanup for us to do. > */ > -void utrace_report_death(struct task_struct *task, struct utrace *utrace, > - bool group_dead, int signal) > +void utrace_report_death(struct task_struct *task, bool group_dead, int signal) > { > + struct utrace *utrace = task_utrace_struct(task); > INIT_REPORT(report); > > BUG_ON(!task->exit_state); From roland at redhat.com Wed Jul 29 00:49:36 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 28 Jul 2009 17:49:36 -0700 (PDT) Subject: [PATCH] tracehooks: remove death_cookie from exit_notify() path In-Reply-To: Oleg Nesterov's message of Wednesday, 29 July 2009 02:40:57 +0200 <20090729004057.GA1974@redhat.com> References: <20090728222053.GA26542@redhat.com> <20090728225656.D79824C721@magilla.sf.frob.com> <20090728232130.GC28339@redhat.com> <20090728233132.A75024C721@magilla.sf.frob.com> <20090729001540.GA664@redhat.com> <20090729004057.GA1974@redhat.com> Message-ID: <20090729004936.73C114C721@magilla.sf.frob.com> > But I think it would be really nice to do this cleanup before sending > the next version of utrace. Let's get through all the utrace cleanups we know we need before we get there. Thanks, Roland From roland at redhat.com Wed Jul 29 00:53:31 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 28 Jul 2009 17:53:31 -0700 (PDT) Subject: [PATCH] simplify do_signal_stop() && utrace_report_jctl() interaction In-Reply-To: Oleg Nesterov's message of Wednesday, 29 July 2009 01:50:46 +0200 <20090728235046.GD28339@redhat.com> References: <20090723002112.6DCE5280@magilla.sf.frob.com> <20090723193414.GB12037@redhat.com> <20090725001933.861BEE7EA@magilla.sf.frob.com> <20090727191003.GA15804@redhat.com> <20090727233507.GA27478@redhat.com> <20090728003635.B08284213C@magilla.sf.frob.com> <20090728012534.GA31866@redhat.com> <20090728013917.120514213C@magilla.sf.frob.com> <20090728194905.GA11304@redhat.com> <20090728221422.045CA4213C@magilla.sf.frob.com> <20090728235046.GD28339@redhat.com> Message-ID: <20090729005331.102AE4C721@magilla.sf.frob.com> > Roland, I'd prefer to send this change separately. Otherwise it will > be really hard to review the unified patch. Do it however you think is best for getting all the generic signal.c and tracehook.h bits merged ASAP. > And I think this will complicate its way to Linus's tree. I _think_ > that "please replace the complex patch which is only needed for utrace > with yet more complex one" request will annoy Andrew a bit ;) I was guessing that the whole final patch would be only a little bigger than the first one, and easier to review as only one thing that touches do_signal_stop() vs 2.6.31. But I leave it to you, or just ask Andrew. > But. I don't really care. Please let me know if you still think it is > better to join these changes. I only care about getting these prerequisites merged upstream as quickly and as smoothly as possible. Thanks, Roland From oleg at redhat.com Wed Jul 29 01:48:20 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 03:48:20 +0200 Subject: [PATCH 0/1] do_signal_stop: do not call tracehook_notify_jctl() in TASK_STOPPED state Message-ID: <20090729014820.GA6197@redhat.com> Andrew, this is on top of signals-tracehook_notify_jctl-change.patch and in fact it can be folded into that patch. Or I can send the unified patch as a replacement, whatever is more convenient to you. But, to clarify, the patch above is correct, this one just tries to improve things, not to fix. This change doesn't depend on utrace patch. Oleg. From oleg at redhat.com Wed Jul 29 01:48:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 03:48:22 +0200 Subject: [PATCH 1/1] do_signal_stop: do not call tracehook_notify_jctl() in TASK_STOPPED state Message-ID: <20090729014822.GA6201@redhat.com> do_signal_stop() can call tracehook_notify_jctl() before decrementing ->group_stop_count and setting TASK_STOPPED/SIGNAL_STOP_STOPPED. This way the tracing hooks can drop and reacquire the siglock freely and do any blocking hooks without potential SIGCONT races. With this patch TASK_STOPPED/SIGNAL_STOP_STOPPED is set only when we know for sure we are going to schedule() after unlock(siglock). Signed-off-by: Oleg Nesterov --- kernel/signal.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) --- __UTRACE/kernel/signal.c~1_DO_SIGNAL_STOP 2009-07-29 03:10:15.000000000 +0200 +++ __UTRACE/kernel/signal.c 2009-07-29 03:17:49.000000000 +0200 @@ -1682,16 +1682,9 @@ void ptrace_notify(int exit_code) static int do_signal_stop(int signr) { struct signal_struct *sig = current->signal; - int stop_count; int notify; - if (sig->group_stop_count > 0) { - /* - * There is a group stop in progress. We don't need to - * start another one. - */ - stop_count = --sig->group_stop_count; - } else { + if (!sig->group_stop_count) { struct task_struct *t; if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || @@ -1703,7 +1696,7 @@ static int do_signal_stop(int signr) */ sig->group_exit_code = signr; - stop_count = 0; + sig->group_stop_count = 1; for (t = next_thread(current); t != current; t = next_thread(t)) /* * Setting state to TASK_STOPPED for a group @@ -1712,25 +1705,28 @@ static int do_signal_stop(int signr) */ if (!(t->flags & PF_EXITING) && !task_is_stopped_or_traced(t)) { - stop_count++; + sig->group_stop_count++; signal_wake_up(t, 0); } - sig->group_stop_count = stop_count; } - - if (stop_count == 0) - sig->flags = SIGNAL_STOP_STOPPED; - current->exit_code = sig->group_exit_code; - __set_current_state(TASK_STOPPED); - /* * If there are no other threads in the group, or if there is - * a group stop in progress and we are the last to stop, - * report to the parent. When ptraced, every thread reports itself. + * a group stop in progress and we are the last to stop, report + * to the parent. When ptraced, every thread reports itself. */ - notify = tracehook_notify_jctl(stop_count == 0 ? CLD_STOPPED : 0, - CLD_STOPPED); - + notify = sig->group_stop_count == 1 ? CLD_STOPPED : 0; + notify = tracehook_notify_jctl(notify, CLD_STOPPED); + /* + * tracehook_notify_jctl() can drop and reacquire siglock, so + * we keep ->group_stop_count != 0 before the call. If SIGCONT + * or SIGKILL comes in between ->group_stop_count == 0. + */ + if (sig->group_stop_count) { + if (!--sig->group_stop_count) + sig->flags = SIGNAL_STOP_STOPPED; + current->exit_code = sig->group_exit_code; + __set_current_state(TASK_STOPPED); + } spin_unlock_irq(¤t->sighand->siglock); if (notify) { From oleg at redhat.com Wed Jul 29 02:01:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 29 Jul 2009 04:01:40 +0200 Subject: [PATCH -mm] introduce tracehook_finish_jctl() helper Message-ID: <20090729020139.GA7381@redhat.com> (textually depends on signals-tracehook_notify_jctl-change.patch) Introduce the empty inline tracehook_finish_jctl() helper called by do_signal_stop() after wakeup. Currently we lack the ability to report this state change. Also fix the comment, it should be placed before schedule(). Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 9 +++++++++ kernel/signal.c | 2 ++ 2 files changed, 11 insertions(+) --- __UTRACE/include/linux/tracehook.h~2_FINISH_JCTL 2009-07-29 03:10:10.000000000 +0200 +++ __UTRACE/include/linux/tracehook.h 2009-07-29 03:51:42.000000000 +0200 @@ -521,6 +521,15 @@ static inline int tracehook_notify_jctl( return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; } +/** + * tracehook_finish_jctl - report about return from job control stop + * + * This is called by do_signal_stop() after wakeup. + */ +static inline void tracehook_finish_jctl(void) +{ +} + #define DEATH_REAP -1 #define DEATH_DELAYED_GROUP_LEADER -2 --- __UTRACE/kernel/signal.c~2_FINISH_JCTL 2009-07-29 03:17:49.000000000 +0200 +++ __UTRACE/kernel/signal.c 2009-07-29 03:57:07.000000000 +0200 @@ -1735,12 +1735,12 @@ static int do_signal_stop(int signr) read_unlock(&tasklist_lock); } + /* Now we don't run again until woken by SIGCONT or SIGKILL */ do { schedule(); } while (try_to_freeze()); - /* - * Now we don't run again until continued. - */ + + tracehook_finish_jctl(); current->exit_code = 0; return 1; From viriato.pina at sapo.pt Wed Jul 29 07:42:36 2009 From: viriato.pina at sapo.pt (viriato@aoredor.org) Date: Wed, 29 Jul 2009 03:42:36 -0400 Subject: =?iso-8859-1?Q?Resolva=20os=20seus=20problemas.=20Em=20casa, =20na=20escola,na=20empresa...?= Message-ID: <20090729081436.F2BB1FB.438069EC@127.0.0.1> MAIL ERROR -------------- next part -------------- An HTML attachment was scrubbed... URL: From topcoats at vaccarezza.com Wed Jul 29 20:07:44 2009 From: topcoats at vaccarezza.com (Haims) Date: Wed, 29 Jul 2009 20:07:44 +0000 Subject: psst Message-ID: Christian Fulfillment in aa Marriage sex Life.www.only9 org From roland at redhat.com Wed Jul 29 22:45:22 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 29 Jul 2009 15:45:22 -0700 (PDT) Subject: [PATCH 1/1] do_signal_stop: do not call tracehook_notify_jctl() in TASK_STOPPED state In-Reply-To: Oleg Nesterov's message of Wednesday, 29 July 2009 03:48:22 +0200 <20090729014822.GA6201@redhat.com> References: <20090729014822.GA6201@redhat.com> Message-ID: <20090729224522.3C3364C791@magilla.sf.frob.com> Acked-by: Roland McGrath From roland at redhat.com Wed Jul 29 22:45:34 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 29 Jul 2009 15:45:34 -0700 (PDT) Subject: [PATCH -mm] introduce tracehook_finish_jctl() helper In-Reply-To: Oleg Nesterov's message of Wednesday, 29 July 2009 04:01:40 +0200 <20090729020139.GA7381@redhat.com> References: <20090729020139.GA7381@redhat.com> Message-ID: <20090729224534.995834C791@magilla.sf.frob.com> Acked-by: Roland McGrath From akpm at linux-foundation.org Wed Jul 29 22:50:07 2009 From: akpm at linux-foundation.org (Andrew Morton) Date: Wed, 29 Jul 2009 15:50:07 -0700 Subject: [PATCH -mm] introduce tracehook_finish_jctl() helper In-Reply-To: <20090729020139.GA7381@redhat.com> References: <20090729020139.GA7381@redhat.com> Message-ID: <20090729155007.f4f5a793.akpm@linux-foundation.org> On Wed, 29 Jul 2009 04:01:40 +0200 Oleg Nesterov wrote: > (textually depends on signals-tracehook_notify_jctl-change.patch) > > Introduce the empty inline tracehook_finish_jctl() helper called by > do_signal_stop() after wakeup. > > Currently we lack the ability to report this state change. > > Also fix the comment, it should be placed before schedule(). > > Signed-off-by: Oleg Nesterov > --- > > include/linux/tracehook.h | 9 +++++++++ > kernel/signal.c | 2 ++ > 2 files changed, 11 insertions(+) > > --- __UTRACE/include/linux/tracehook.h~2_FINISH_JCTL 2009-07-29 03:10:10.000000000 +0200 > +++ __UTRACE/include/linux/tracehook.h 2009-07-29 03:51:42.000000000 +0200 > @@ -521,6 +521,15 @@ static inline int tracehook_notify_jctl( > return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; > } > > +/** > + * tracehook_finish_jctl - report about return from job control stop > + * > + * This is called by do_signal_stop() after wakeup. > + */ > +static inline void tracehook_finish_jctl(void) > +{ > +} > + > #define DEATH_REAP -1 > #define DEATH_DELAYED_GROUP_LEADER -2 > > --- __UTRACE/kernel/signal.c~2_FINISH_JCTL 2009-07-29 03:17:49.000000000 +0200 > +++ __UTRACE/kernel/signal.c 2009-07-29 03:57:07.000000000 +0200 > @@ -1735,12 +1735,12 @@ static int do_signal_stop(int signr) > read_unlock(&tasklist_lock); > } > > + /* Now we don't run again until woken by SIGCONT or SIGKILL */ > do { > schedule(); > } while (try_to_freeze()); > - /* > - * Now we don't run again until continued. > - */ > + > + tracehook_finish_jctl(); > current->exit_code = 0; > Confused. This patch has no effect. From ananth at in.ibm.com Thu Jul 30 09:55:14 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Thu, 30 Jul 2009 15:25:14 +0530 Subject: [RFC][PATCH 0/3] Utrace based non-disruptive application core dumps - V1 Message-ID: <20090730095514.GH5232@in.ibm.com> This series is an RFC for utrace-based non-disruptive application core dumper. Per Roland McGrath, this is possibly one of the common use-cases for utrace. This is the first foray of mine into the hairy core dump land. Admittedly, I may have missed some (not so) subtle issues that need careful consideration. The current implementation uses a /proc trigger. Every process gains a new /proc//gen_core 'write-only' file. Echoing a value of '1' will cause the core-dump to be generated. As with fatal core-dumps, the core file will be saved in the same directory as the location from where the application was started. The core dump has a format core.., where the timestamp is the value of ktime_get() at the time of calling the binfmt->core_dump(). The current implementation uses a completion(). However, this precludes the possibility of a process syncrhonously asking for its own dump (trying this usecase causes the application to hang indefinitely). I am told this is a much needed feature that Linux lacks. Awaiting comments... Regards, Ananth From ananth at in.ibm.com Thu Jul 30 09:56:12 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Thu, 30 Jul 2009 15:26:12 +0530 Subject: [PATCH 1/3] Create the /proc trigger In-Reply-To: <20090730095514.GH5232@in.ibm.com> References: <20090730095514.GH5232@in.ibm.com> Message-ID: <20090730095612.GI5232@in.ibm.com> Create the /proc//gen-core file that is the trigger for non-disruptive application core dumps. Writing any value other than 1 to this file is invalid. Signed-off-by: Ananth N Mavinakayanahalli --- fs/proc/Makefile | 1 fs/proc/base.c | 3 ++ fs/proc/internal.h | 3 ++ fs/proc/proc_gencore.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+) Index: utrace-13jul/fs/proc/Makefile =================================================================== --- utrace-13jul.orig/fs/proc/Makefile +++ utrace-13jul/fs/proc/Makefile @@ -26,3 +26,4 @@ proc-$(CONFIG_PROC_VMCORE) += vmcore.o proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o proc-$(CONFIG_PRINTK) += kmsg.o proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o +proc-$(CONFIG_UTRACE) += proc_gencore.o Index: utrace-13jul/fs/proc/base.c =================================================================== --- utrace-13jul.orig/fs/proc/base.c +++ utrace-13jul/fs/proc/base.c @@ -2558,6 +2558,9 @@ static const struct pid_entry tgid_base_ #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), #endif +#ifdef CONFIG_UTRACE + REG("gen_core", S_IWUSR, proc_gen_core_operations), +#endif #ifdef CONFIG_TASK_IO_ACCOUNTING INF("io", S_IRUGO, proc_tgid_io_accounting), #endif Index: utrace-13jul/fs/proc/internal.h =================================================================== --- utrace-13jul.orig/fs/proc/internal.h +++ utrace-13jul/fs/proc/internal.h @@ -60,6 +60,9 @@ extern const struct file_operations proc extern const struct file_operations proc_pagemap_operations; extern const struct file_operations proc_net_operations; extern const struct inode_operations proc_net_inode_operations; +#ifdef CONFIG_UTRACE +extern const struct file_operations proc_gen_core_operations; +#endif /* CONFIG_UTRACE */ void free_proc_entry(struct proc_dir_entry *de); Index: utrace-13jul/fs/proc/proc_gencore.c =================================================================== --- /dev/null +++ utrace-13jul/fs/proc/proc_gencore.c @@ -0,0 +1,65 @@ +/* + * Non-disruptive application core dump + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2009 + */ + +#include +#include +#include "internal.h" + +#include + +static ssize_t gen_core_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct task_struct *task; + char buffer[PROC_NUMBUF], *end; + unsigned int val; + int ret; + + ret = -EFAULT; + memset(buffer, 0, sizeof(buffer)); + if (count > sizeof(buffer) - 1) + count = sizeof(buffer) - 1; + if (copy_from_user(buffer, buf, count)) + goto out_no_task; + + ret = -EINVAL; + val = (unsigned int)simple_strtoul(buffer, &end, 0); + if (*end == '\n') + end++; + if ((end - buffer == 0) || (val == 0) || (val > 1)) + goto out_no_task; + + ret = -ESRCH; + task = get_proc_task(file->f_dentry->d_inode); + if (!task) + goto out_no_task; + + ret = end - buffer; + + /* TODO: call core dumper */ + + put_task_struct(task); +out_no_task: + return ret; +} + +const struct file_operations proc_gen_core_operations = { + .write = gen_core_write, +}; From ananth at in.ibm.com Thu Jul 30 09:56:56 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Thu, 30 Jul 2009 15:26:56 +0530 Subject: [PATCH 2/3] Quiesce all threads of a process In-Reply-To: <20090730095514.GH5232@in.ibm.com> References: <20090730095514.GH5232@in.ibm.com> Message-ID: <20090730095656.GJ5232@in.ibm.com> o Attach utrace engines to all threads of the process o Stub in handlers of interest o Quiesce all threads of the process o Currently this patch does nothing interesting beyond the point. Once the threads are quiesced, it just calls complete(), which causes the 'echo' command to return. The current implementation uses two top level structures: - core_proc: One per process. It tracks the number of threads in the process and the count of quiesced threads. This also lives in the *data of the struct utrace_engine. - core_task: One per task, also chained to the core_proc. Currently, we rendezvous threads via UTRACE_INTERRUPT. The intention is to take a non-disruptive core dump, triggered by the last thread of the process that quiesced, from its quiesce callback. The ideal way of doing it would've been via UTRACE_STOP. However, for the most trivial of cases (say bash at waiting at the command line), the task won't quiesce until some activity on the shell; similarly for any thread blocked in the kernel. There are a number of points that need clarification/fixing in the patch: - Surely, there are races that I've ignored. - The mechanism to attach engines to all threads of the process is less than optimal. The 'correct' way to do it is similar to follow how uprobes does it. (https://www.redhat.com/archives/utrace-devel/2009-June/msg00022.html). A better possibility is to have a utrace callback that implements it in the utrace layer. - Do we need the exec callback? Is it implemented correctly here? - There possibly are more gotchas that am currently unaware of. Signed-off-by: Ananth N Mavinakayanahalli --- fs/proc/proc_gencore.c | 354 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 353 insertions(+), 1 deletion(-) Index: utrace-13jul/fs/proc/proc_gencore.c =================================================================== --- utrace-13jul.orig/fs/proc/proc_gencore.c +++ utrace-13jul/fs/proc/proc_gencore.c @@ -24,10 +24,350 @@ #include +static const struct utrace_engine_ops core_ops; + +/* All threads of a process having the same utrace ops */ +struct core_proc { + /* list of struct core_task */ + struct list_head list; + + struct task_struct *tgid_task; + atomic_t num_threads; + atomic_t num_quiesced; + /* Protects list and num_threads above */ + spinlock_t lock; + + struct completion complete; +}; + +struct core_task { + struct list_head list; + struct task_struct *task; + struct utrace_engine *engine; + bool quiesced; +}; + +static void cleanup_core_proc(struct core_proc *core_proc) +{ + struct core_task *core_task, *temp; + int ret; + + if (core_proc == NULL) + return; + + spin_lock(&core_proc->lock); + if (list_empty(&core_proc->list)) + goto out; + + /* walk core_proc->list and free core_task */ + list_for_each_entry_safe(core_task, temp, &core_proc->list, list) { + if (core_task->engine) + /* do we really care about the retval here? */ + ret = utrace_control(core_task->task, + core_task->engine, UTRACE_DETACH); + list_del(&core_task->list); + kfree(core_task); + } +out: + spin_unlock(&core_proc->lock); + kfree(core_proc); + return; +} + +static int setup_core_task(struct task_struct *t, struct core_proc *core_proc) +{ + struct core_task *core_task; + int ret = 0; + + if (!t || !core_proc) + return -EINVAL; + + core_task = kzalloc(sizeof(*core_task), GFP_KERNEL); + if (!core_task) + return -ENOMEM; + + /* + * The engine->data will point to core_proc. + * + * If a core dump is already in progress, a new request will fail + * with -EALREADY since the core dump engine is EXCLUSIVE. + */ + core_task->engine = utrace_attach_task(t, (UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_MATCH_OPS | UTRACE_ATTACH_EXCLUSIVE), + &core_ops, core_proc); + if (core_task->engine == ERR_PTR(-EEXIST)) { + ret = -EALREADY; + goto err_out; + } + if (IS_ERR(core_task->engine)) { + ret = PTR_ERR(core_task->engine); + goto err_out; + } + + /* + * We don't need a utrace_barrier() here since we are just setting + * events the first time and there is no risk of a prior requested + * event callback being in progress. + */ + ret = utrace_set_events(t, core_task->engine, UTRACE_EVENT(QUIESCE) | + UTRACE_EVENT(CLONE) | UTRACE_EVENT(EXIT)); + if (ret) { + /* -EINPROGRESS indicates a callback is due soon */ + if (ret != -EINPROGRESS) { + ret = utrace_control(core_task->task, + core_task->engine, UTRACE_DETACH); + goto err_out; + } + } + + INIT_LIST_HEAD(&core_task->list); + core_task->task = t; + + spin_lock(&core_proc->lock); + list_add_tail(&core_task->list, &core_proc->list); + atomic_inc(&core_proc->num_threads); + spin_unlock(&core_proc->lock); + + return ret; +err_out: + kfree(core_task); + return ret; +} + +static struct core_task *get_core_task(struct task_struct *task, + struct core_proc *core_proc) +{ + struct core_task *core_task, *temp; + + if (!task || !core_proc) + return NULL; + + spin_lock(&core_proc->lock); + list_for_each_entry_safe(core_task, temp, &core_proc->list, list) { + if (core_task->task == task) { + spin_unlock(&core_proc->lock); + return core_task; + } + } + spin_unlock(&core_proc->lock); + return NULL; +} + +static inline void set_quiesced(struct core_task *core_task, + struct core_proc *core_proc) +{ + if (!core_task->quiesced) { + core_task->quiesced = 1; + atomic_inc(&core_proc->num_quiesced); + } +} + +/* XXX Do quiesce_*thread routines below need to return a value? */ +static void quiesce_thread(struct core_task *core_task, + struct core_proc *core_proc) +{ + int ret; + + if (!core_task || !core_proc) + return; + + /* + * If the task in question is just starting up, it will quiesce + * before heading to userspace. Don't force it through + * UTRACE_INTERRUPT. + */ + if (!(core_task->task->flags & PF_STARTING)) { + ret = utrace_control(core_task->task, core_task->engine, + UTRACE_INTERRUPT); + if (ret == 0) + set_quiesced(core_task, core_proc); + } + return; +} + +static void quiesce_all_threads(struct core_proc *core_proc, bool quiesce) +{ + struct core_task *core_task, *temp; + int ret = 0; + + if (!core_proc) + return; + + list_for_each_entry_safe(core_task, temp, &core_proc->list, list) { + if (quiesce) + quiesce_thread(core_task, core_proc); + else + ret = utrace_control(core_task->task, + core_task->engine, UTRACE_DETACH); + } + return; +} + +static u32 core_quiesce(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, unsigned long event) +{ + struct core_proc *core_proc = (struct core_proc *)engine->data; + struct core_task *core_task = get_core_task(task, core_proc); + + set_quiesced(core_task, core_proc); + if (atomic_read(&core_proc->num_quiesced) == + atomic_read(&core_proc->num_threads)) { + + /* All threads quiesced, do your thing :-) */ + + /* Let everyone run, indicate we are done! */ + quiesce_all_threads(core_proc, false); + complete(&core_proc->complete); + } else { + /* Keep thread quiescent */ + return UTRACE_STOP; + } + /* All done, detach */ + return UTRACE_DETACH; +} + +static u32 core_clone(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *parent, unsigned long clone_flags, + struct task_struct *child) +{ + struct core_proc *core_proc = (struct core_proc *)engine->data; + struct core_task *core_task; + int ret; + + if (clone_flags & CLONE_THREAD) { + ret = setup_core_task(child, core_proc); + /* + * -EINPROGRESS => thread on the way to quiesce + * -EALREADY => we may be racing with attach_utrace_engines + * and it may already have attached an engine for us. + */ + if (ret && ((ret != -EINPROGRESS) || (ret != -EALREADY))) { + /* Error! Bail out */ + complete(&core_proc->complete); + return UTRACE_RESUME; + } + core_task = get_core_task(child, core_proc); + if (core_task) + quiesce_thread(core_task, core_proc); + } + + /* We'll quiesce during clone_complete check soon */ + return UTRACE_RESUME; +} + +/* + * Process exec()ing. Abort and exit from here + * + * XXX: + * a. Is this necessary? + * b. Are we safe here wrt the core dump being in progress? + */ +static u32 core_exec(enum utrace_resume_action action, + struct utrace_engine *engine, struct task_struct *task, + const struct linux_binfmt *fmt, const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct core_proc *core_proc = (struct core_proc *)engine->data; + + if (core_proc) + complete(&core_proc->complete); + return UTRACE_DETACH; +} + +/* + * XXX Are there subtle races when one thread of a multi-threaded process + * is exiting while the non-disruptive core dump is in progress? + * + * Of course, we still need to honor SIGKILL during core dumping. + */ +static u32 core_exit(enum utrace_resume_action action, + struct utrace_engine *engine, struct task_struct *task, + long orig_code, long *code) +{ + struct core_task *core_task; + struct core_proc *core_proc = (struct core_proc *)engine->data; + + core_task = get_core_task(task, core_proc); + if (core_task) { + spin_lock(&core_proc->lock); + atomic_dec(&core_proc->num_threads); + list_del(&core_task->list); + kfree(core_task); + + /* If we are the last task, ask for cleanup! */ + if (unlikely(list_empty(&core_proc->list))) + complete(&core_proc->complete); + spin_unlock(&core_proc->lock); + } + return UTRACE_DETACH; +} + +static const struct utrace_engine_ops core_ops = +{ + .report_clone = core_clone, /* new thread */ + .report_quiesce = core_quiesce, + .report_exec = core_exec, + .report_exit = core_exit, /* thread exit */ +}; + +static struct core_proc *attach_utrace_engines(struct task_struct *task) +{ + int ret = 0; + struct task_struct *t = task; + struct core_proc *core_proc; + + if (!task) + return ERR_PTR(-EINVAL); + + core_proc = kzalloc(sizeof(*core_proc), GFP_KERNEL); + if (!core_proc) + return ERR_PTR(-ENOMEM); + core_proc->tgid_task = task; + INIT_LIST_HEAD(&core_proc->list); + atomic_set(&core_proc->num_threads, 0); + atomic_set(&core_proc->num_quiesced, 0); + spin_lock_init(&core_proc->lock); + init_completion(&core_proc->complete); + + rcu_read_lock(); + do { + get_task_struct(t); + rcu_read_unlock(); + ret = setup_core_task(t, core_proc); + /* + * -EINPROGRESS => we are on our way to quiesce. + * -EEXIST => we may be racing with core_clone and it has + * already attached an engine for us. + */ + if (ret && ((ret != EINPROGRESS) || (ret != -EALREADY))) + goto err_core_task; + rcu_read_lock(); + put_task_struct(t); + ret = 0; + t = next_thread(t); + } while (t != task); + + rcu_read_unlock(); + /* + * Now that we have attached engines to all threads, explicitly + * ask for each thread to be quiesced. + */ + quiesce_all_threads(core_proc, true); + return core_proc; + +err_core_task: + put_task_struct(t); + cleanup_core_proc(core_proc); + return ERR_PTR(ret); +} + static ssize_t gen_core_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct task_struct *task; + struct core_proc *core_proc; char buffer[PROC_NUMBUF], *end; unsigned int val; int ret; @@ -53,8 +393,20 @@ static ssize_t gen_core_write(struct fil ret = end - buffer; - /* TODO: call core dumper */ + /* Attach an engine to each thread */ + core_proc = attach_utrace_engines(task); + if (IS_ERR(core_proc)) { + ret = (int)PTR_ERR(core_proc); + goto out_no_engines; + } + + /* Wait for the dump to complete or error out */ + wait_for_completion(&core_proc->complete); + + /* Cleanup after */ + cleanup_core_proc(core_proc); +out_no_engines: put_task_struct(task); out_no_task: return ret; From ananth at in.ibm.com Thu Jul 30 09:57:48 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Thu, 30 Jul 2009 15:27:48 +0530 Subject: [PATCH 3/3] Plugin the core-dumper In-Reply-To: <20090730095514.GH5232@in.ibm.com> References: <20090730095514.GH5232@in.ibm.com> Message-ID: <20090730095748.GK5232@in.ibm.com> Plugin the actual worker core-dumper routine. This is possibly a naive implementation, and looks very similar to do_coredump(), with certain subtle differences: - We currently don't honour rlimits (should we?). The coredump_filter though, is honoured. - We build the core_state and core_thread chains on the fly. - No pipe support. The core is saved in the format core.. where the timestamp is the ktime_get() value when the dump occurs. Certainly, there are assumptions I've made that may be incorrect. The prototype works for the most part. Only occasionally, a subtle race which am yet to determine, causes a failure. As with fatal dumps, gdb is able to decode the core. Signed-off-by: Ananth N Mavinakayanahalli --- fs/proc/proc_gencore.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) Index: utrace-13jul/fs/proc/proc_gencore.c =================================================================== --- utrace-13jul.orig/fs/proc/proc_gencore.c +++ utrace-13jul/fs/proc/proc_gencore.c @@ -19,6 +19,7 @@ */ #include +#include #include #include "internal.h" @@ -47,14 +48,153 @@ struct core_task { bool quiesced; }; +static void cleanup_core_state(struct core_state *core_state) +{ + struct core_thread *core_thread, *temp; + + if (!core_state) + return; + + core_thread = core_state->dumper.next; + while (core_thread != NULL) { + temp = core_thread->next; + kfree(core_thread); + core_thread = temp; + } + kfree(core_state); +} + +static struct core_state *build_core_state(struct core_proc *core_proc) +{ + struct task_struct *t = current; + struct core_task *core_task, *temp; + struct core_state *core_state; + + if (!core_proc) + return ERR_PTR(-EINVAL); + + /* + * We already know all threads have either been quiesced or blocked + * in the kernel. Even for threads bloced in the kernel, we know for + * sure that they'll not run userspace before quiescing. + * + * If this is a single-threaded process and its already exiting, + * we still hold the mmap_sem and we'll also see it in core_exit. + */ + core_state = kzalloc(sizeof(*core_state), GFP_KERNEL); + if (!core_state) + return ERR_PTR(-ENOMEM); + + core_state->dumper.task = t; + core_state->dumper.next = NULL; + t->mm->core_state = core_state; + /* Make sure this is visible to do_exit */ + wmb(); + + list_for_each_entry_safe(core_task, temp, &core_proc->list, list) { + struct core_thread *core_thread; + + if (core_task->task == t) + continue; + core_thread = kzalloc(sizeof(*core_thread), GFP_KERNEL); + if (!core_thread) { + cleanup_core_state(core_state); + return ERR_PTR(-ENOMEM); + } + core_thread->task = core_task->task; + core_thread->next = xchg(&core_state->dumper.next, + core_thread); + } + return core_state; +} + +/* + * A 0 or negative return => failure. + * elf_core_dump returns 1 on SUCCESS + */ +static int write_core(struct core_proc *core_proc) +{ + struct core_state *core_state; + char corename[CORENAME_MAX_SIZE + 1]; + struct mm_struct *mm = current->mm; + struct linux_binfmt *binfmt; + struct inode *inode; + struct file *file; + int retval = -1; + int flag = 0; + + binfmt = current->binfmt; + if (!core_proc || !binfmt || !binfmt->core_dump) + return -EINVAL; + + down_write(&mm->mmap_sem); + if (mm->core_state || !get_dumpable(mm)) { + up_write(&mm->mmap_sem); + return -EALREADY; + } + + core_state = build_core_state(core_proc); + if (IS_ERR(core_state)) { + up_write(&mm->mmap_sem); + return PTR_ERR(core_state); + } + + up_write(&mm->mmap_sem); + + /* For now, core files will have the core..timestamp format */ + memset(corename, 0x00, (CORENAME_MAX_SIZE + 1)); + strncpy(corename, "core.", strlen("core.")); + snprintf((corename + strlen(corename)), + (CORENAME_MAX_SIZE - strlen(corename)), + "%d.", task_tgid_vnr(current)); + snprintf((corename + strlen(corename)), + (CORENAME_MAX_SIZE - strlen(corename)), + "%lld", (ktime_to_us(ktime_get()))); + + file = filp_open(corename, + O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, + 0600); + if (IS_ERR(file)) + return PTR_ERR(file); + inode = file->f_path.dentry->d_inode; + if (inode->i_nlink > 1) + goto close_fail; + if (d_unhashed(file->f_path.dentry)) + goto close_fail; + if (!S_ISREG(inode->i_mode)) + goto close_fail; + if (inode->i_uid != current_fsuid()) + goto close_fail; + if (!file->f_op) + goto close_fail; + if (!file->f_op->write) + goto close_fail; + if (do_truncate(file->f_path.dentry, 0, 0, file) != 0) + goto close_fail; + + /* XXX coresize is currently hardcoded. need to fix that */ + retval = binfmt->core_dump(0, NULL, file, 0xFFFFFFFF); + +close_fail: + filp_close(file, NULL); + cleanup_core_state(core_state); + current->mm->core_state = NULL; + wmb(); + return retval; +} + static void cleanup_core_proc(struct core_proc *core_proc) { struct core_task *core_task, *temp; + struct core_state *core_state = core_proc->tgid_task->mm->core_state; int ret; if (core_proc == NULL) return; + if (core_state) + cleanup_core_state(core_state); + spin_lock(&core_proc->lock); if (list_empty(&core_proc->list)) goto out; @@ -215,6 +355,10 @@ static u32 core_quiesce(enum utrace_resu atomic_read(&core_proc->num_threads)) { /* All threads quiesced, do your thing :-) */ + int ret = write_core(core_proc); + if (ret == -EALREADY) + /* Dump already in progress, hold thread */ + return UTRACE_STOP; /* Let everyone run, indicate we are done! */ quiesce_all_threads(core_proc, false); From oleg at redhat.com Thu Jul 30 16:30:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 30 Jul 2009 18:30:35 +0200 Subject: [PATCH -mm] introduce tracehook_finish_jctl() helper In-Reply-To: <20090729155007.f4f5a793.akpm@linux-foundation.org> References: <20090729020139.GA7381@redhat.com> <20090729155007.f4f5a793.akpm@linux-foundation.org> Message-ID: <20090730163035.GA3617@redhat.com> On 07/29, Andrew Morton wrote: > > On Wed, 29 Jul 2009 04:01:40 +0200 > Oleg Nesterov wrote: > > > +static inline void tracehook_finish_jctl(void) > > +{ > > +} > > + > > #define DEATH_REAP -1 > > #define DEATH_DELAYED_GROUP_LEADER -2 > > > > --- __UTRACE/kernel/signal.c~2_FINISH_JCTL 2009-07-29 03:17:49.000000000 +0200 > > +++ __UTRACE/kernel/signal.c 2009-07-29 03:57:07.000000000 +0200 > > @@ -1735,12 +1735,12 @@ static int do_signal_stop(int signr) > > read_unlock(&tasklist_lock); > > } > > > > + /* Now we don't run again until woken by SIGCONT or SIGKILL */ > > do { > > schedule(); > > } while (try_to_freeze()); > > - /* > > - * Now we don't run again until continued. > > - */ > > + > > + tracehook_finish_jctl(); > > current->exit_code = 0; > > > > Confused. This patch has no effect. Yes, currently tracehook_finish_jctl() does nothing. This patch is needed to add the functional changes later, without touching the code outside of tracehook/etc. It is like tracehook_notify_resume() which does nothing until we add the real tracing. Oleg. From ssc at finproduct.it Thu Jul 30 15:52:25 2009 From: ssc at finproduct.it (SSC Srl) Date: Thu, 30 Jul 2009 17:52:25 +0200 Subject: =?utf-8?q?DA_UNA_GRANDE_BANCA_UN_FINANZIAMENTO_=E2=80=A6_?= Message-ID: <20090730172831.12556.612911045.swift@192.168.5.5> An HTML attachment was scrubbed... URL: From oleg at redhat.com Fri Jul 31 01:06:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 31 Jul 2009 03:06:43 +0200 Subject: [PATCH 0/6] misc utrace-core cleanups Message-ID: <20090731010643.GA8044@redhat.com> Changes: 1-4: s/signal/SIGKILL/ in utrace_finish_jctl's comment 5-6: new, by previous discussion Oleg. From oleg at redhat.com Fri Jul 31 01:06:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 31 Jul 2009 03:06:46 +0200 Subject: [PATCH 1/6] utrace_report_jctl: do not play with the group-stop state Message-ID: <20090731010646.GA8053@redhat.com> (depends on signals-tracehook_notify_jctl-change-do_signal_stop-do-not-call-tracehook_notify_jctl-in-task_stopped-state.patch) Now that do_signal_stop() calls tracehook_notify_jctl() in TASK_RUNNING we can simplify utrace_report_jctl(), task_is_stopped() case is not possible. Signed-off-by: Oleg Nesterov ---- kernel/utrace.c | 20 -------------------- 1 file changed, 20 deletions(-) --- __UTRACE/kernel/utrace.c~1_REPORT_JCTL 2009-07-29 03:11:19.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-31 01:54:29.000000000 +0200 @@ -1607,18 +1607,7 @@ void utrace_report_jctl(int notify, int struct task_struct *task = current; struct utrace *utrace = task_utrace_struct(task); INIT_REPORT(report); - bool stop = task_is_stopped(task); - /* - * We have to come out of TASK_STOPPED in case the event report - * hooks might block. Since we held the siglock throughout, it's - * as if we were never in TASK_STOPPED yet at all. - */ - if (stop) { - __set_current_state(TASK_RUNNING); - task->signal->flags &= ~SIGNAL_STOP_STOPPED; - ++task->signal->group_stop_count; - } spin_unlock_irq(&task->sighand->siglock); /* @@ -1647,16 +1636,7 @@ void utrace_report_jctl(int notify, int REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), report_jctl, what, notify); - /* - * Retake the lock, and go back into TASK_STOPPED - * unless the stop was just cleared. - */ spin_lock_irq(&task->sighand->siglock); - if (stop && task->signal->group_stop_count > 0) { - __set_current_state(TASK_STOPPED); - if (--task->signal->group_stop_count == 0) - task->signal->flags |= SIGNAL_STOP_STOPPED; - } } /* From oleg at redhat.com Fri Jul 31 01:06:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 31 Jul 2009 03:06:49 +0200 Subject: [PATCH 2/6] use tracehook_finish_jctl() to clear ->stopped Message-ID: <20090731010649.GA8056@redhat.com> (depends on signals-introduce-tracehook_finish_jctl-helper.patch) Use tracehook_finish_jctl() to clear utrace->stopped. From now we shouldn't worry about ->stopped "leaking" after jctl stop. Signed-off-by: Oleg Nesterov --- include/linux/utrace.h | 2 ++ include/linux/tracehook.h | 2 ++ kernel/utrace.c | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+) --- __UTRACE/include/linux/utrace.h~2_FINISH_JCTL 2009-07-29 03:10:09.000000000 +0200 +++ __UTRACE/include/linux/utrace.h 2009-07-31 02:15:34.000000000 +0200 @@ -109,6 +109,8 @@ void utrace_report_death(struct task_str __attribute__((weak)); void utrace_report_jctl(int notify, int type) __attribute__((weak)); +void utrace_finish_jctl(void) + __attribute__((weak)); void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, struct pt_regs *regs) __attribute__((weak)); --- __UTRACE/include/linux/tracehook.h~2_FINISH_JCTL 2009-07-31 02:13:57.000000000 +0200 +++ __UTRACE/include/linux/tracehook.h 2009-07-31 02:15:34.000000000 +0200 @@ -528,6 +528,8 @@ static inline int tracehook_notify_jctl( */ static inline void tracehook_finish_jctl(void) { + if (task_utrace_flags(current)) + utrace_finish_jctl(); } #define DEATH_REAP -1 --- __UTRACE/kernel/utrace.c~2_FINISH_JCTL 2009-07-31 01:54:29.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-31 02:15:34.000000000 +0200 @@ -1640,6 +1640,24 @@ void utrace_report_jctl(int notify, int } /* + * Called without locks. + */ +void utrace_finish_jctl(void) +{ + struct utrace *utrace = task_utrace_struct(current); + /* + * While in TASK_STOPPED, we can be considered safely + * stopped by utrace_do_stop(). Clear ->stopped if we + * were woken by signal. + */ + if (utrace->stopped) { + spin_lock(&utrace->lock); + utrace->stopped = false; + spin_unlock(&utrace->lock); + } +} + +/* * Called iff UTRACE_EVENT(EXIT) flag is set. */ void utrace_report_exit(long *exit_code) From oleg at redhat.com Fri Jul 31 01:06:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 31 Jul 2009 03:06:51 +0200 Subject: [PATCH 3/6] utrace_do_stop: s/STOPPED/TRACED/ to protect against SIGCONT Message-ID: <20090731010651.GA8064@redhat.com> utrace_do_stop() sets utrace->stopped but leaves the tracee in TASK_STOPPED state. This means SIGCONT can wake up the tracee and fool the tracer. Set ->state = TASK_TRACED and update the comments in utrace_do_stop() and utrace_finish_jctl(). Signed-off-by: Oleg Nesterov ---- kernel/utrace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) --- __UTRACE/kernel/utrace.c~3_STOP_TRACED 2009-07-31 02:15:34.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-31 02:25:32.000000000 +0200 @@ -788,8 +788,9 @@ static bool utrace_do_stop(struct task_s } else if (task_is_stopped(target)) { /* * Stopped is considered quiescent; when it wakes up, it will - * go through utrace_get_signal() before doing anything else. + * go through utrace_finish_jctl() before doing anything else. */ + __set_task_state(target, TASK_TRACED); utrace->stopped = stopped = true; } else if (!utrace->report && !utrace->interrupt) { utrace->report = 1; @@ -1646,9 +1647,8 @@ void utrace_finish_jctl(void) { struct utrace *utrace = task_utrace_struct(current); /* - * While in TASK_STOPPED, we can be considered safely - * stopped by utrace_do_stop(). Clear ->stopped if we - * were woken by signal. + * While in TASK_STOPPED, we can be considered safely stopped by + * utrace_do_stop(). Clear ->stopped if we were woken by SIGKILL. */ if (utrace->stopped) { spin_lock(&utrace->lock); From oleg at redhat.com Fri Jul 31 01:06:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 31 Jul 2009 03:06:54 +0200 Subject: [PATCH 4/6] utrace_report_jctl/utrace_get_signal: do not play with ->stopped Message-ID: <20090731010654.GA8067@redhat.com> Now that we always clear ->stopped in utrace_finish_jctl(), we can cleanup utrace_report_jctl() and utrace_get_signal(), they do not need to worry about ->stopped == T any longer. Note that the change in utrace_report_jctl() removes start_report()'s work too. Contrary to what the comment says, REPORT() does call start_report(). >From now the rules for ->stopped are very simple: - it is set by utrace_stop() or utrace_do_stop() - it is clered by utrace_wakeup(), or if the tracee is woken by signal we clear it in finish_utrace_stop() or utrace_finish_jctl() Signed-off-by: Oleg Nesterov ---- kernel/utrace.c | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) --- __UTRACE/kernel/utrace.c~4_CLEANUP 2009-07-31 02:25:32.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-31 02:29:32.000000000 +0200 @@ -1611,29 +1611,6 @@ void utrace_report_jctl(int notify, int spin_unlock_irq(&task->sighand->siglock); - /* - * We get here with CLD_STOPPED when we've just entered - * TASK_STOPPED, or with CLD_CONTINUED when we've just come - * out but not yet been through utrace_get_signal() again. - * - * While in TASK_STOPPED, we can be considered safely - * stopped by utrace_do_stop() and detached asynchronously. - * If we woke up and checked task->utrace_flags before that - * was finished, we might be here with utrace already - * removed or in the middle of being removed. - * - * If we are indeed attached, then make sure we are no - * longer considered stopped while we run callbacks. - */ - spin_lock(&utrace->lock); - utrace->stopped = 0; - /* - * Do start_report()'s work too since we already have the lock anyway. - */ - utrace->report = 0; - splice_attaching(utrace); - spin_unlock(&utrace->lock); - REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), report_jctl, what, notify); @@ -1925,8 +1902,6 @@ int utrace_get_signal(struct task_struct * interrupt path, so clear the flags asking for those. */ utrace->interrupt = utrace->report = utrace->signal_handler = 0; - utrace->stopped = 0; - /* * Make sure signal_pending() only returns true * if there are real signals pending. @@ -1954,22 +1929,13 @@ int utrace_get_signal(struct task_struct event = 0; ka = NULL; memset(return_ka, 0, sizeof *return_ka); - } else if ((task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) == 0 && - !utrace->stopped) { + } else if ((task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) == 0) { /* * If no engine is interested in intercepting signals, * let the caller just dequeue them normally. */ return 0; } else { - if (unlikely(utrace->stopped)) { - spin_unlock_irq(&task->sighand->siglock); - spin_lock(&utrace->lock); - utrace->stopped = 0; - spin_unlock(&utrace->lock); - spin_lock_irq(&task->sighand->siglock); - } - /* * Steal the next signal so we can let tracing engines * examine it. From the signal number and sigaction, From oleg at redhat.com Fri Jul 31 01:06:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 31 Jul 2009 03:06:56 +0200 Subject: [PATCH 5/6] finish_utrace_stop: check ->stopped lockless Message-ID: <20090731010656.GA8074@redhat.com> finish_utrace_stop() can check ->stopped lockless. It was set by us, we can't miss it. Signed-off-by: Oleg Nesterov ---- kernel/utrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- __UTRACE/kernel/utrace.c~5_FINISH_STOP 2009-07-31 02:29:32.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-31 02:35:50.000000000 +0200 @@ -353,8 +353,8 @@ static inline bool finish_utrace_stop(st * utrace_wakeup() clears @utrace->stopped before waking us up. * We're officially awake if it's clear. */ - spin_lock(&utrace->lock); if (unlikely(utrace->stopped)) { + spin_lock(&utrace->lock); /* * If we're here with it still set, it must have been * signal_wake_up() instead, waking us up for a SIGKILL. @@ -364,8 +364,8 @@ static inline bool finish_utrace_stop(st spin_unlock_irq(&task->sighand->siglock); utrace->stopped = 0; killed = true; + spin_unlock(&utrace->lock); } - spin_unlock(&utrace->lock); return killed; } From oleg at redhat.com Fri Jul 31 01:06:59 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 31 Jul 2009 03:06:59 +0200 Subject: [PATCH 6/6] get_utrace_lock: do not check EXIT_DEAD Message-ID: <20090731010659.GA8077@redhat.com> get_utrace_lock() checks ->state != EXIT_DEAD to make sure it safe to use ->utrace. This is unneeded since ->utrace was embedded into task_struct. If we can read ->state, we can read ->utrace as well. Signed-off-by: Oleg Nesterov ---- kernel/utrace.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) --- __UTRACE/kernel/utrace.c~6_GET_UTRACE_LOCK 2009-07-31 02:35:50.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-07-31 02:47:42.000000000 +0200 @@ -493,27 +493,17 @@ static struct utrace *get_utrace_lock(st } utrace = &target->utrace; - if (unlikely(target->exit_state == EXIT_DEAD)) { + spin_lock(&utrace->lock); + if (unlikely(!engine->ops) || + unlikely(engine->ops == &utrace_detached_ops)) { /* - * If all engines detached already, utrace is clear. - * Otherwise, we're called after utrace_release_task might - * have started. A call to this engine's report_reap - * callback might already be in progress. + * By the time we got the utrace lock, + * it had been reaped or detached already. */ + spin_unlock(&utrace->lock); utrace = ERR_PTR(-ESRCH); - } else { - spin_lock(&utrace->lock); - if (unlikely(!engine->ops) || - unlikely(engine->ops == &utrace_detached_ops)) { - /* - * By the time we got the utrace lock, - * it had been reaped or detached already. - */ - spin_unlock(&utrace->lock); - utrace = ERR_PTR(-ESRCH); - if (!attached && engine->ops == &utrace_detached_ops) - utrace = ERR_PTR(-ERESTARTSYS); - } + if (!attached && engine->ops == &utrace_detached_ops) + utrace = ERR_PTR(-ERESTARTSYS); } rcu_read_unlock(); From mldireto at tudoemoferta.com.br Thu Jul 30 23:35:17 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Thu, 30 Jul 2009 20:35:17 -0300 Subject: Livro+CD+DVD As 100 Regras de Ouro do Sucesso! Message-ID: <9c218cb64a629d37924e70630015efeb@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From jkenisto at us.ibm.com Fri Jul 31 16:59:11 2009 From: jkenisto at us.ibm.com (Jim Keniston) Date: Fri, 31 Jul 2009 09:59:11 -0700 Subject: [PATCH 2/3] Quiesce all threads of a process In-Reply-To: <20090730095656.GJ5232@in.ibm.com> References: <20090730095514.GH5232@in.ibm.com> <20090730095656.GJ5232@in.ibm.com> Message-ID: <1249059551.5082.14.camel@localhost.localdomain> On Thu, 2009-07-30 at 15:26 +0530, Ananth N Mavinakayanahalli wrote: > +static u32 core_clone(enum utrace_resume_action action, ... > + /* > + * -EINPROGRESS => thread on the way to quiesce > + * -EALREADY => we may be racing with attach_utrace_engines > + * and it may already have attached an engine for us. > + */ > + if (ret && ((ret != -EINPROGRESS) || (ret != -EALREADY))) { ((ret != -EINPROGRESS) || (ret != -EALREADY)) ??? Assuming EINPROGRESS != EALREADY, this test is always true. I think you want && here, in which case you can dispense with most of the parens. ... > +/* > + * Process exec()ing. Abort and exit from here > + * > + * XXX: > + * a. Is this necessary? I think it's a good idea to handle the exec case. But since dumping core for an exec-ing process is a rather bizarre thing to attempt, you can probably handle it however is most convenient for you. > + * b. Are we safe here wrt the core dump being in progress? Assuming all threads are quiesced before you start your actual core dump, there's no way one of them can exec while you're dumping. > + */ > +static u32 core_exec(enum utrace_resume_action action, > + struct utrace_engine *engine, struct task_struct *task, > + const struct linux_binfmt *fmt, const struct linux_binprm *bprm, > + struct pt_regs *regs) > +... > + > +static struct core_proc *attach_utrace_engines(struct task_struct *task) > +{ ... > + /* > + * -EINPROGRESS => we are on our way to quiesce. > + * -EEXIST => we may be racing with core_clone and it has > + * already attached an engine for us. > + */ > + if (ret && ((ret != EINPROGRESS) || (ret != -EALREADY))) s/||/&&/ -- as above. Jim From eternaleye at gmail.com Fri Jul 31 19:57:46 2009 From: eternaleye at gmail.com (Alex Elsayed) Date: Fri, 31 Jul 2009 12:57:46 -0700 Subject: [PATCH 2/3] Quiesce all threads of a process References: <20090730095514.GH5232@in.ibm.com> <20090730095656.GJ5232@in.ibm.com> <1249059551.5082.14.camel@localhost.localdomain> Message-ID: Jim Keniston wrote: >> + /* >> + * -EINPROGRESS => we are on our way to quiesce. >> + * -EEXIST => we may be racing with core_clone and it has >> + * already attached an engine for us. >> + */ >> + if (ret && ((ret != EINPROGRESS) || (ret != -EALREADY))) > > s/||/&&/ -- as above. This one's also missing a negation for EINPROGRESS, if the comments are correct. From reservaciones at costaclubresort.com Fri Jul 31 21:12:59 2009 From: reservaciones at costaclubresort.com (Costa club Resort) Date: Fri, 31 Jul 2009 17:12:59 -0400 Subject: Escape to the beach Message-ID: An HTML attachment was scrubbed... URL: From fche at redhat.com Fri Jul 31 22:08:49 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Fri, 31 Jul 2009 18:08:49 -0400 Subject: gdbstub/uprobes problems: uprobe_unregister with halted target In-Reply-To: References: <20090731194622.GC12318@redhat.com> Message-ID: <20090731220849.GD12318@redhat.com> Hi, guys - I'm running into a recurrent problem on my gdbstub+uprobes prototype. (git://web.elastic.org/~fche/utrace-ext.git utrace-gdbstub-uprobes) The gist is that running a unregister_uprobe upon a stopped process (single-threaded, stoped via a UTRACE_STOP event) appears to hang indefinitely. There appear to be no contended locks in this case, just this loop in uprobes_core.c:unregister_uprobe: ppt->state = UPROBE_REMOVING; list_add_tail(&ppt->pd_node, &uproc->pending_uprobes); (void) quiesce_all_threads(uproc, &cur_utask_quiescing); up_write(&uproc->rwsem); if (cur_utask_quiescing) /* Current task is probing its own process. */ (void) utask_fake_quiesce(cur_utask_quiescing); else wait_event(ppt->waitq, ppt->state != UPROBE_REMOVING); >From a systemtap script that probes the goings-on nearby: .... 15505 gdb(7435): unregister_uprobe u=0xffff8800220c1660 15520 gdb(7435): uprobe_get_tg_leader p=0x546 15528 gdb(7435): uprobe_get_tg_leader return=0xffff880078e8d680 15536 gdb(7435): uprobe_find_utask tsk=0xffff8800375c48e0 15543 gdb(7435): uprobe_find_utask return=0x0 15716 gdb(7435): uprobe_find_process tg_leader=0xffff880078e8d680 15726 gdb(7435): uprobe_find_process return=0xffff880075bc77e0 15736 gdb(7435): uprobe_free_kimg uk=0xffff8800220c1088 15762 gdb(7435): uprobe_free_kimg 15770 gdb(7435): list_add_tail new=0xffff8800377a42b8 head=0xffff880075bc7960 15775 gdb(7435): list_add_tail 15782 gdb(7435): quiesce_all_threads uproc=0xffff880075bc77e0 cur_utask_quiescing=0xffff88004c5f1dc0 15790 gdb(7435): check_uproc_quiesced uproc=0xffff880075bc77e0 tsk=0xffff880037d0a470 15795 gdb(7435): check_uproc_quiesced return=0x0 15800 gdb(7435): quiesce_all_threads return=0x1 .... hang here .... The target process side is also hung: zsh D 0000000000000002 3568 1288 1259 0x00000080 ffff880078c57b98 0000000000000046 0000000000000000 0000000000011d4a ffff88006d4b8000 0000000000000000 ffff880078c57f50 00007fff138b0858 ffff88006d4b83b8 000000000000f968 ffff88006d4b83b8 00000000001d5740 Call Trace: [] ? gdb_uprobe_handler+0x79/0xc2 [] ? gdb_uprobe_handler+0x79/0xc2 [] ? gdb_uprobe_handler+0x79/0xc2 [] __mutex_lock_common+0x207/0x38a [] ? gdb_uprobe_handler+0x79/0xc2 [] mutex_lock_nested+0x3c/0x41 [] gdb_uprobe_handler+0x79/0xc2 [] uprobe_report_signal+0x4e5/0x959 [] ? lock_release_holdtime+0x2c/0x11d [] ? _spin_unlock+0x2b/0x30 [] utrace_get_signal+0x33d/0x5bd [] ? get_signal_to_deliver+0x4c/0x3b6 [] get_signal_to_deliver+0xf6/0x3b6 [] ? kvm_clock_read+0x21/0x23 [] do_notify_resume+0x89/0x746 [] ? __up_read+0x76/0x7f [] ? paranoid_userspace+0x39/0x5a [] ? trace_hardirqs_on_caller+0x126/0x14a [] paranoid_userspace+0x4b/0x5a and the corresponding function call graph was: 3854 zsh(1350): uprobe_report_signal action=0x0 engine=0xffff88003ac36078 tsk=0xffff880037d0a470 regs=0xffff880059097f58 info 3867 zsh(1350): utrace_attach_pid pid=0xffff880078e8d680 flags=0x1 ops=0xffffffff81443be0 data=0x0 3881 zsh(1350): utrace_attach_task target=0xffff880037d0a470 flags=0x1 ops=0xffffffff81443be0 data=0x0 3890 zsh(1350): matching_engine utrace=0xffff880037d0aad8 flags=0x1 ops=0xffffffff81443be0 data=0x0 3901 zsh(1350): matching_engine return=0xffff880078d190f0 3907 zsh(1350): utrace_attach_task return=0xffff880078d190f0 3914 zsh(1350): put_task_struct t=0xffff880037d0a470 3918 zsh(1350): put_task_struct 3923 zsh(1350): utrace_attach_pid return=0xffff880078d190f0 3931 zsh(1350): uretprobe_set_trampoline uproc=0xffff880075bc77e0 tsk=0xffff880037d0a470 3947 zsh(1350): kzalloc").call size=0x40 flags=? 3955 zsh(1350): kzalloc").return return=0xffff88001ec27ee0 3986 zsh(1350): uretprobe_set_trampoline 3999 zsh(1350): clear_utrace_quiesce utask=0xffff880078f53290 resume=0x0 4007 zsh(1350): utask_adjust_flags utask=0xffff880078f53290 set=0x0 flags=0x1 4012 zsh(1350): utask_adjust_flags 4017 zsh(1350): clear_utrace_quiesce 4028 zsh(1350): uprobe_find_probept uproc=0xffff880075bc77e0 vaddr=0x419dd0 4034 zsh(1350): uprobe_find_probept return=0xffff8800377a4248 4041 zsh(1350): gdb_uprobe_handler up=0xffff8800220c1660 regs=0xffff880059097f58 4060 zsh(1350): gdb_uprobe_handler 4073 zsh(1350): utask_adjust_flags utask=0xffff880078f53290 set=0x1 flags=0x1 4080 zsh(1350): utrace_set_events_pid pid=0xffff880078e8d680 engine=0xffff88003ac36078 eventmask=0x131d 4088 zsh(1350): utrace_set_events target=0xffff880037d0a470 engine=0xffff88003ac36078 events=0x131d 4095 zsh(1350): get_utrace_lock target=0xffff880037d0a470 engine=0xffff88003ac36078 attached=0x1 4108 zsh(1350): get_utrace_lock return=0xffff880037d0aad8 4210 zsh(1350): utrace_set_events return=0x0 4215 zsh(1350): utrace_set_events_pid return=0x0 4220 zsh(1350): utask_adjust_flags 4227 zsh(1350): uprobe_put_process uproc=0xffff880075bc77e0 in_callback=0x1 4232 zsh(1350): uprobe_put_process return=0x0 4237 zsh(1350): uprobe_report_signal return=0x13 4242 zsh(1350): finish_callback utrace=0xffff880037d0aad8 report=0xffff880059097d98 engine=0xffff88003ac36078 ret=0x13 4248 zsh(1350): finish_callback return=0x0 4254 zsh(1350): finish_resume_report report=0xffff880059097d98 task=0xffff880037d0a470 utrace=0xffff880037d0aad8 4261 zsh(1350): utrace_reset task=0xffff880037d0a470 utrace=0xffff880037d0aad8 action=0xffff880059097d98 4268 zsh(1350): put_detached_list list=0xffff880059097cc8 4273 zsh(1350): put_detached_list 4278 zsh(1350): utrace_reset 4284 zsh(1350): utrace_stop task=0xffff880037d0a470 utrace=0xffff880037d0aad8 report=0x0 So it's as if there may be some sort of conflict between send_sig() and unregister_uprobes(), but I'm not sure. Do you have any initial advice about what's supposed to work / not work, or what else to instrument? - FChE From jkenisto at us.ibm.com Sat Aug 1 00:05:24 2009 From: jkenisto at us.ibm.com (Jim Keniston) Date: Fri, 31 Jul 2009 17:05:24 -0700 Subject: gdbstub/uprobes problems: uprobe_unregister with halted target In-Reply-To: <20090731220849.GD12318@redhat.com> References: <20090731194622.GC12318@redhat.com> <20090731220849.GD12318@redhat.com> Message-ID: <1249085124.5082.83.camel@localhost.localdomain> On Fri, 2009-07-31 at 18:08 -0400, Frank Ch. Eigler wrote: > Hi, guys - > > I'm running into a recurrent problem on my gdbstub+uprobes prototype. > (git://web.elastic.org/~fche/utrace-ext.git utrace-gdbstub-uprobes) > > The gist is that running a unregister_uprobe upon a stopped process > (single-threaded, stoped via a UTRACE_STOP event) appears to hang > indefinitely. There appear to be no contended locks in this case, > just this loop in uprobes_core.c:unregister_uprobe: > > ppt->state = UPROBE_REMOVING; > list_add_tail(&ppt->pd_node, &uproc->pending_uprobes); > > (void) quiesce_all_threads(uproc, &cur_utask_quiescing); > up_write(&uproc->rwsem); > if (cur_utask_quiescing) > /* Current task is probing its own process. */ > (void) utask_fake_quiesce(cur_utask_quiescing); > else > wait_event(ppt->waitq, ppt->state != UPROBE_REMOVING); > > >From a systemtap script that probes the goings-on nearby: > > .... > 15505 gdb(7435): unregister_uprobe u=0xffff8800220c1660 > 15520 gdb(7435): uprobe_get_tg_leader p=0x546 > 15528 gdb(7435): uprobe_get_tg_leader return=0xffff880078e8d680 > 15536 gdb(7435): uprobe_find_utask tsk=0xffff8800375c48e0 > 15543 gdb(7435): uprobe_find_utask return=0x0 > 15716 gdb(7435): uprobe_find_process tg_leader=0xffff880078e8d680 > 15726 gdb(7435): uprobe_find_process return=0xffff880075bc77e0 > 15736 gdb(7435): uprobe_free_kimg uk=0xffff8800220c1088 > 15762 gdb(7435): uprobe_free_kimg > 15770 gdb(7435): list_add_tail new=0xffff8800377a42b8 head=0xffff880075bc7960 > 15775 gdb(7435): list_add_tail > 15782 gdb(7435): quiesce_all_threads uproc=0xffff880075bc77e0 cur_utask_quiescing=0xffff88004c5f1dc0 > 15790 gdb(7435): check_uproc_quiesced uproc=0xffff880075bc77e0 tsk=0xffff880037d0a470 > 15795 gdb(7435): check_uproc_quiesced return=0x0 > 15800 gdb(7435): quiesce_all_threads return=0x1 > .... hang here .... check_uproc_quiesced() returning 0 indicates that uprobes thinks that the probed thread is not yet quiesced. So unregister_uprobe() is waiting for that to happen. But you say the probed thread is already stopped via a UTRACE_STOP event. So I'd think that uprobe_stop_thread() (which should be called by quiesce_all_threads()) should notice this and mark the thread as quiesced. Does uprobe_stop_thread() actually get called? If so, what does utrace_control_pid() return to it? > > The target process side is also hung: > > zsh D 0000000000000002 3568 1288 1259 0x00000080 > ffff880078c57b98 0000000000000046 0000000000000000 0000000000011d4a > ffff88006d4b8000 0000000000000000 ffff880078c57f50 00007fff138b0858 > ffff88006d4b83b8 000000000000f968 ffff88006d4b83b8 00000000001d5740 > Call Trace: > [] ? gdb_uprobe_handler+0x79/0xc2 > [] ? gdb_uprobe_handler+0x79/0xc2 > [] ? gdb_uprobe_handler+0x79/0xc2 > [] __mutex_lock_common+0x207/0x38a > [] ? gdb_uprobe_handler+0x79/0xc2 > [] mutex_lock_nested+0x3c/0x41 > [] gdb_uprobe_handler+0x79/0xc2 > [] uprobe_report_signal+0x4e5/0x959 > [] ? lock_release_holdtime+0x2c/0x11d > [] ? _spin_unlock+0x2b/0x30 > [] utrace_get_signal+0x33d/0x5bd > [] ? get_signal_to_deliver+0x4c/0x3b6 > [] get_signal_to_deliver+0xf6/0x3b6 > [] ? kvm_clock_read+0x21/0x23 > [] do_notify_resume+0x89/0x746 > [] ? __up_read+0x76/0x7f > [] ? paranoid_userspace+0x39/0x5a > [] ? trace_hardirqs_on_caller+0x126/0x14a > [] paranoid_userspace+0x4b/0x5a > > and the corresponding function call graph was: > > 3854 zsh(1350): uprobe_report_signal action=0x0 engine=0xffff88003ac36078 tsk=0xffff880037d0a470 regs=0xffff880059097f58 info > 3867 zsh(1350): utrace_attach_pid pid=0xffff880078e8d680 flags=0x1 ops=0xffffffff81443be0 data=0x0 > 3881 zsh(1350): utrace_attach_task target=0xffff880037d0a470 flags=0x1 ops=0xffffffff81443be0 data=0x0 > 3890 zsh(1350): matching_engine utrace=0xffff880037d0aad8 flags=0x1 ops=0xffffffff81443be0 data=0x0 > 3901 zsh(1350): matching_engine return=0xffff880078d190f0 > 3907 zsh(1350): utrace_attach_task return=0xffff880078d190f0 > 3914 zsh(1350): put_task_struct t=0xffff880037d0a470 > 3918 zsh(1350): put_task_struct > 3923 zsh(1350): utrace_attach_pid return=0xffff880078d190f0 I can't think of why utrace_attach_pid() would get called here. > 3931 zsh(1350): uretprobe_set_trampoline uproc=0xffff880075bc77e0 tsk=0xffff880037d0a470 > 3947 zsh(1350): kzalloc").call size=0x40 flags=? > 3955 zsh(1350): kzalloc").return return=0xffff88001ec27ee0 > 3986 zsh(1350): uretprobe_set_trampoline > 3999 zsh(1350): clear_utrace_quiesce utask=0xffff880078f53290 resume=0x0 > 4007 zsh(1350): utask_adjust_flags utask=0xffff880078f53290 set=0x0 flags=0x1 > 4012 zsh(1350): utask_adjust_flags > 4017 zsh(1350): clear_utrace_quiesce > 4028 zsh(1350): uprobe_find_probept uproc=0xffff880075bc77e0 vaddr=0x419dd0 > 4034 zsh(1350): uprobe_find_probept return=0xffff8800377a4248 > 4041 zsh(1350): gdb_uprobe_handler up=0xffff8800220c1660 regs=0xffff880059097f58 > 4060 zsh(1350): gdb_uprobe_handler > 4073 zsh(1350): utask_adjust_flags utask=0xffff880078f53290 set=0x1 flags=0x1 > 4080 zsh(1350): utrace_set_events_pid pid=0xffff880078e8d680 engine=0xffff88003ac36078 eventmask=0x131d > 4088 zsh(1350): utrace_set_events target=0xffff880037d0a470 engine=0xffff88003ac36078 events=0x131d > 4095 zsh(1350): get_utrace_lock target=0xffff880037d0a470 engine=0xffff88003ac36078 attached=0x1 > 4108 zsh(1350): get_utrace_lock return=0xffff880037d0aad8 > 4210 zsh(1350): utrace_set_events return=0x0 > 4215 zsh(1350): utrace_set_events_pid return=0x0 > 4220 zsh(1350): utask_adjust_flags > 4227 zsh(1350): uprobe_put_process uproc=0xffff880075bc77e0 in_callback=0x1 > 4232 zsh(1350): uprobe_put_process return=0x0 > 4237 zsh(1350): uprobe_report_signal return=0x13 > 4242 zsh(1350): finish_callback utrace=0xffff880037d0aad8 report=0xffff880059097d98 engine=0xffff88003ac36078 ret=0x13 > 4248 zsh(1350): finish_callback return=0x0 > 4254 zsh(1350): finish_resume_report report=0xffff880059097d98 task=0xffff880037d0a470 utrace=0xffff880037d0aad8 > 4261 zsh(1350): utrace_reset task=0xffff880037d0a470 utrace=0xffff880037d0aad8 action=0xffff880059097d98 > 4268 zsh(1350): put_detached_list list=0xffff880059097cc8 > 4273 zsh(1350): put_detached_list > 4278 zsh(1350): utrace_reset > 4284 zsh(1350): utrace_stop task=0xffff880037d0a470 utrace=0xffff880037d0aad8 report=0x0 I'm confused here. Is the traced task getting hung in gdb_uprobe_handler() -- per your call trace -- or utrace_stop() (or elsewhere) -- per your call graph? > > So it's as if there may be some sort of conflict between send_sig() > and unregister_uprobes(), but I'm not sure. Do you have any initial > advice about what's supposed to work / not work, or what else to > instrument? > > > - FChE > From mldireto at tudoemoferta.com.br Fri Jul 31 23:23:32 2009 From: mldireto at tudoemoferta.com.br (Englobe Sistemas e E-commerce) Date: Fri, 31 Jul 2009 20:23:32 -0300 Subject: Novos planos voce empreendedor de visao Message-ID: <5893931662af8255a6e24607001dbf72@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From roland at redhat.com Sat Aug 1 23:32:07 2009 From: roland at redhat.com (Roland McGrath) Date: Sat, 1 Aug 2009 16:32:07 -0700 (PDT) Subject: [PATCH -mm] introduce tracehook_finish_jctl() helper In-Reply-To: Andrew Morton's message of Wednesday, 29 July 2009 15:50:07 -0700 <20090729155007.f4f5a793.akpm@linux-foundation.org> References: <20090729020139.GA7381@redhat.com> <20090729155007.f4f5a793.akpm@linux-foundation.org> Message-ID: <20090801233207.E1FEB4C7FF@magilla.sf.frob.com> > Confused. This patch has no effect. Indeed, the three patches changing do_signal_stop() have no immediate material effect. They all just clean up the code and prepare the hooks that utrace (or something like it) needs to make tracing stops mesh well with job control stops. I'd thought it might be simpler for review to just roll these three together and send you a single patch to replace signals-tracehook_notify_jctl-change.patch; but Oleg decided to keep it sliced smaller. Thanks, Roland From roland at redhat.com Sun Aug 2 00:01:43 2009 From: roland at redhat.com (Roland McGrath) Date: Sat, 1 Aug 2009 17:01:43 -0700 (PDT) Subject: [PATCH 3/6] utrace_do_stop: s/STOPPED/TRACED/ to protect against SIGCONT In-Reply-To: Oleg Nesterov's message of Friday, 31 July 2009 03:06:51 +0200 <20090731010651.GA8064@redhat.com> References: <20090731010651.GA8064@redhat.com> Message-ID: <20090802000143.9F0684C800@magilla.sf.frob.com> I've merged these (up to 5/6 so far). Now I'm looking at all the uses of ->stopped. * utrace_set_events could test task_is_stopped_or_traced() || ->exit_state * utrace_control: could test task_is_traced() || ->exit_state && !(->utrace_flags & _UTRACE_DEATH_EVENTS) (or let utrace_do_stop test the latter) * finish_utrace_stop detects signal_wake_up(,1) (SIGKILL) (And the rest are just the bookkeeping to keep it set/cleared.) So I think it's now true that the only thing ->stopped is buying us is that finish_utrace_stop test. Do you agree? Perhaps we can just replace that with __fatal_signal_pending (or inline it, that should be a one-insn test), or with a check on SIGNAL_GROUP_KILLED or suchlike if we had that. (Some test for group-exit-or-exec.) If we can indeed clean up each of those uses with a different test that is sufficient for the case, then we can drop the utrace->stopped bit entirely. That means we actually wouldn't need tracehook_finish_jctl for anything, AFAICT. Thanks, Roland From roland at redhat.com Sun Aug 2 00:22:25 2009 From: roland at redhat.com (Roland McGrath) Date: Sat, 1 Aug 2009 17:22:25 -0700 (PDT) Subject: [PATCH 5/6] finish_utrace_stop: check ->stopped lockless In-Reply-To: Oleg Nesterov's message of Friday, 31 July 2009 03:06:56 +0200 <20090731010656.GA8074@redhat.com> References: <20090731010656.GA8074@redhat.com> Message-ID: <20090802002225.89D534C87C@magilla.sf.frob.com> > finish_utrace_stop() can check ->stopped lockless. It was set by us, > we can't miss it. We enter utrace_stop() for some stop. Either then or later, a group jctl stop finishes and sets SIGNAL_STOP_STOPPED. Later, utrace_wakeup() sees that and we switch to TASK_STOPPED after clearing ->stopped. We stay in jctl stop for a few days. Some new debugger comes along with utrace_control(,,UTRACE_STOP) and utrace_do_stop() switches us to TASK_TRACED after setting ->stopped. Meanwhile, SIGCONT is coming along and clearing SIGNAL_STOP_STOPPED (sibling threads run again, etc.). Now the debugger calls utrace_control(,,UTRACE_RESUME), so utrace_wakeup clears ->stopped and wakes us up. Now ->stopped was just an instant ago set and then cleared on the other CPU and we are running. Are we really sure that we see it as clear rather than set? (I think there is also a racier version without jctl stops at all, just where utrace_wakeup+utrace_do_stop+utrace_wakeup all came and went before we actually got scheduled.) I might be overlooking some interlock that covers this. I put the patch in, anyway. But I think that I can even worry about this is a good indicator that we'd probably be happier if we can indeed get rid of ->stopped altogether. Thanks, Roland From roland at redhat.com Sun Aug 2 00:44:12 2009 From: roland at redhat.com (Roland McGrath) Date: Sat, 1 Aug 2009 17:44:12 -0700 (PDT) Subject: [PATCH 6/6] get_utrace_lock: do not check EXIT_DEAD In-Reply-To: Oleg Nesterov's message of Friday, 31 July 2009 03:06:59 +0200 <20090731010659.GA8077@redhat.com> References: <20090731010659.GA8077@redhat.com> Message-ID: <20090802004412.939744C87D@magilla.sf.frob.com> > get_utrace_lock() checks ->state != EXIT_DEAD to make sure it safe > to use ->utrace. This is unneeded since ->utrace was embedded into > task_struct. If we can read ->state, we can read ->utrace as well. I see. My immediate reaction to this was that it should have more comments that make clear it's relying on that rule of struct utrace lifetime. That thought was motivated by my interest in changing the data structure (again) to using a struct utrace pointer in the future. But the reason that it's potentially worthwhile to have a pointer that can go away is to reclaim the memory on live detach. Even if we do go that way again, we won't reintroduce the same kind of race with utrace_release_task, because it's far simpler just to delay the deallocation until tracehook_free_task. So whatever magic we would need in get_utrace_lock would be worrying only about interlocks with utrace_reset, not with ->exit_state changes. i.e. it is orthogonal to this change. Thanks, Roland From roland at redhat.com Mon Aug 3 06:35:00 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 2 Aug 2009 23:35:00 -0700 (PDT) Subject: [RFC][PATCH 0/3] Utrace based non-disruptive application core dumps - V1 In-Reply-To: Ananth N Mavinakayanahalli's message of Thursday, 30 July 2009 15:25:14 +0530 <20090730095514.GH5232@in.ibm.com> References: <20090730095514.GH5232@in.ibm.com> Message-ID: <20090803063500.3969241064@magilla.sf.frob.com> > This series is an RFC for utrace-based non-disruptive application core > dumper. Per Roland McGrath, this is possibly one of the common use-cases > for utrace. I'm not sure whether it's the "common use-case" (debuggers are still that, I think). What I've noticed is that this is a feature that many users often request (i.e. "much better gcore") and dearly want. It's a fine example of the sort of thing that utrace is intended to facilitate. > This is the first foray of mine into the hairy core dump land. I guess I've been roaming around there far too long, because the actual core dump parts seem like simple stuff to me. And you didn't even delve into the core dump parts, you just call the old code! So I'll take this as "foray ... into hairy utrace-ish synchronization issues", and then not believe you about the "first" part. ;-) > Admittedly, I may have missed some (not so) subtle issues that need > careful consideration. My reactions are in three areas that I'll discuss somewhat independently. 1. technical issues with using binfmt->core_dump() 2. utrace issues 3. feature semantics issues 1. binfmt->core_dump() What you're really calling is elf_core_dump(). I don't think we really care about any feature to write other formats of core dump, so we can think about what that code is doing rather than worrying about any supposed general case of the binfmt hook. elf_core_dump() expects to be called from do_coredump(), most importantly, after coredump_wait(). Here every other task sharing current->mm is known to be uninterruptibly blocked in exit_mm(). That makes it impossible for anything to change any mappings (the only ways to do it are on your own mm, not on another process). Because it expects this, elf_core_dump() does its mm-scanning work without mmap_sem. (See the comment near the top of elf_core_dump.) There are several reasons why you can't have such an ironclad guarantee for your case. The first reason is simply that you don't try to stop all the threads in the mm, only the thread group. I think that is perfectly fine as a feature decision for the thing you're writing as far as which threads to include in the dump--but that's separate from the kernel robustness mandate, under which you cannot presume no such races. The rest of the reasons are in the realm of hairy synchronization issues, which I'll go into later. In short, I think you want down_read(&mm->mmap_sem) around calling binfmt->core_dump(). The other issue in this area is overloading mm->core_state. (Obviously you have to do this to use the existing elf_core_dump code that anchors its internal state records there.) Since you're doing this, you have to make 100% sure that no task in the mm can get to exit_mm() and look at your struct core_state. (Or else, you have to make it safe for that to happen, by the way you set up and tear down your struct, which may be tricky.) In utrace terms, this happens after the exit event and before the death event. One simple way is to just hold down_write(&mm->mmap_sem) around calling elf_core_dump(). Then threads can get to exit_mm() but they will just block in down_read(). But for several reasons, I think that is improper and a bad plan. The other possible ways tie into the utrace issues I'll get into below, but they are also imperfect. (I'm not really offering solutions to these problems here, more just citing some cans of worms. At the end, I'll have some conclusions stemming from the whole can collection.) 2. utrace stuff EXEC is not an interesting event here. That event is after everything has changed. So either you got the exec'ing thread stopped before it actually started the exec (i.e. syscall entry tracing or before), or you didn't. If you did, then you are done and gone before the exec happens. If you didn't, then you don't really care that an exec just happened. That just happens to be the new state of the process before you took the snapshot. In an MT exec, the other threads will have died and been reaped before the EXEC event is reported. So an MT exec case is really just like any other case where you have one thread stopped successfully (in this case, after it exec'd), and meanwhile some other threads died before you got them stopped. EXIT is a potentially interesting event, but it's not the right one for the way you are using it. That event means "starting to exit". Then the thread does potentially a whole lot, conceivably including arbitrary blocks, changing all sorts of shared state, etc., before the DEATH event. So it's not right to wash your hands of the thread in EXIT and immediately forget it exists--it could be doing more interfering things thereafter. Moreover, you might have already missed the EXIT event when you attach (utrace_set_events can't tell, unlike for DEATH and REAP) and then you would get that callback before your death callback. You don't really need or want a separate death callback. Your quiesce callback will get called first anyway. It needs to check for the death case, check either the event argument or task->exit_state. When it's called for the DEATH event, you shouldn't record the task as "quiescent". You can't (necessarily) make user_regset calls on a dead thread. Instead, that case is where you should drop your record of the task as you are now doing on the EXIT event. I said EXIT is "potentially interesting". You don't need that event for any bookkeeping reason. EXIT and SYSCALL_ENTRY are the two events that are "potentially interesting" in the same way. These are the two event reports that precede some complex kernel activity, rather than being closely succeeded by user mode. If anyone is tracing these, then you will get report_quiesce callbacks at these events. But you are not guaranteed those callbacks just because you are listening for QUIESCE. So if you want to maximize on "make all threads report quickly", then you should enable the EXIT and SYSCALL_ENTRY event bits. (There's no point for all the other events, because your UTRACE_STOP ensures a report_quiesce callback of some sort either at or immediately after each other event.) You don't actually need to define any callback functions for these. You don't have any special work for them, the report_quiesce callback will have done it already. You can make report_quiesce call utrace_set_events to reset the bits and that takes effect immediately so it doesn't try to make the event-specific callback for the very same event that this report_quiesce call is about. After you've gotten report_quiesce, you don't necessarily need any events enabled any more (only perhaps QUIESCE or DEATH or REAP for bookkeeping purposes). That brings us to the SIGKILL question. Whatever place you got each thread to stop, it can always be suddenly woken up by a SIGKILL. There are two issues with this and two approaches to coping with each. First is bookkeeping: that you don't get confused about the state of the thread and the utrace_engine. For that you can make sure to have a REAP, DEATH, or QUIESCE callback enabled (QUIESCE will get you a callback for death) that cleans up your bookkeeping synchronously so that you can never try to do anything with the dead task. Or, you can do it "passively" just by having your asynchronous uses cope with -ESRCH returns from utrace calls to mean the non-error case of the task having been reaped and your engine implicitly detached. Importantly, you'd have to use utrace_prepare_examine et al properly around access to the task (user_regset et al) unless you hold your own task refs. Second is safety in actually examining the threads. For that you have the two same sorts of option. First option, you make sure to have a DEATH or QUIESCE callback that cleans up your own bookkeeping synchronously so you ignore the thread. Second option, you cope gracefully with failure in your asynchronous examination. To do it safely you have to hold task refs and/or use utrace_prepare_examine et al around the user_regset calls et al and be prepared to punt the thread silently when they fail. Each of those is potentially hairy to get exactly right. And, in fact you have to do some measure of the second just to do the first. That is, DEATH event reports are after the point at which user_regset calls may no longer work (they could return -EIO or something). So your calls have to be robust to that, even if you are synchronizing as much as you can. Finally, there is the issue of blocked/nonresponsive threads. This is not so much an issue about how you use utrace per se. It's just a set of facts and constraints on what choices you have for the semantics. Threads that are in the kernel, either blocked, or arbitrary long-running (though that shouldn't happen) won't report a QUIESCE (or any) event for an arbitrarily long time. The normal case is a thread blocked in a system call, though there could be others. I'll discuss the semantics question below. The upshot for the mechanics of the code is that when utrace_control() returned -EINPROGRESS you have to notice if the thread is not responding quickly, and decide what to do. 3. semantics of the feature Calling elf_core_dump() is obviously attractive when writing the code--there's a big chunk you just call and don't think about. That's natural and fine for a first prototype. But it imposes a variety of constraints on how you can do things. Some of these impinge on the implementation issues I've mentioned above. Others just affect what options you have for the flexibility and semantics of the feature you provide. You create the file and do all the i/o in the context of some thread in the process being examined. This has two kinds of issues: "disruptive" issues, and feature semantics issues. Of the former, the possibilities I can think of immediately are SIGXFZ and quota warnings that could be generated for the process, but there may be other issues of that ilk. Those are positive disruptions; there is also the related ilk of "perturbations", such as i/o charged to the process (or CPU time for filesystem or i/o work). As to the latter, the first point is that I think it's just not what people would expect by default. I think people expect "like gcore", i.e. the instigator of the dump must have permissions for full inspection and control a la ptrace, and then all the actual file writing happens entirely in the context of the dumper, not the dumpee. (Context here means all of privilege, filesystem namespace, etc.) The more general point is that we'd like the dumper to be in a position to offer all manner of flexibility in where and how the data gets sent. The next issue about the feature is just the general issue of flexibility. One thing people have mused could be nice about a "fancy new core dumper" is the chance for arbitrary new amounts of flexibility in exactly what a dump-taker wants to do. An example is the choices that vma_dump_size() makes, i.e. which memory to include in the dump. These are controlled by coredump_filter, so a crude level of control for that example is possible just by fiddling that momentarily. But one can imagine fancier users wanting to apply more complex criteria there. Another aspect of flexibility is what you do about threads that will not stop quickly. It's not kosher to make user_regset calls on these. They might well claim to work, but some or all of their data could be bogus, could be leaking uninitialized kernel stack bits, etc. Among options that are purely nonperturbing, you have several in the abstract. But using elf_core_dump() only gives you one: omit the threads entirely. You have to keep them out of your list to prevent it from making those bogus user_regset calls, so you don't have any other choice. I mentioned "purely nonperturbing" options. There is also the option to perturb, and variants thereof. That is, you can use UTRACE_INTERRUPT. Using it blindly is what today's "gcore" does implicitly--interrupt every system call, no matter the implications for the program logic. That's always an option, though it does not qualify as nondisruptive. Its effect is like using SIGSTOP + SIGCONT (when the process is ignoring SIGCONT). For many system calls, this is no problem: they abort with -ERESTART*, get rolled back, and restart as if nothing happened. For various things like i/o calls this is also true but it may also be that there are perturbations, ones that are officially harmless, but still could affect the program's experience of the system. For other things like some sleep calls, some supposedly restart correctly, but you can't be entirely sure about the effects. There are probably others that are just completely pertrubed by "interrupt with no signal". >From there, you can get into a world of "lightly perturbing" options. That is, you can get fancy with looking at the state of the thread with asm/syscall.h calls and decide what is safe to do. If it's blocked and not in a syscall, that ought to be in a page fault (or maybe some other kind of machine exception). It should be harmless to interrupt that, since the faulting insn will just start over again in the end. For various particular syscalls recognized from syscall_get_nr(), you can assert that it's safe to interrupt them because they are known to restart harmlessly enough. For example, futex is this way (and should be a very common case). But it all gets into a touchy area. I think you see why I raise this as a "flexibility" question rather than citing one right thing to do. Back to purely nonperturbing options, there are a few that make sense off hand. Skipping the thread as if it doesn't exist at all is one, but not the one I'd ever suggest. The next obvious simple thing is to include a record (struct elf_prstatus) for the task, but just give all zero for its register data (pr_reg). That says there is a thread, and all the info that is easily at hand about it, but not what it's doing. The most satisfying thing is like that, but fill in "as much as you can" for the register data (you can get at least what /proc/pid/syscall has, if not more). I have an idea about that, but that can wait until after we've gotten to a place where we have any choice in the matter. (The most satisfying thing overall is probably to combine that latter with a simple version of the "lightly perturbing", e.g. interrupt if not in a syscall or if in a futex or wait call.) Leaving nonresponsive threads aside, there is another angle of flexibility that I always figured people might like in gcore. That is, how much it synchronizes. For a coherent complete snapshot, you need every thread to stop. But even if everything goes completely smoothly in the terms we've been discussing it, that pause could be a significant perturbation, e.g. in a large process with many many threads to stop and a lot of memory to spend i/o time dumping. For nondisruptive sampling, you might want the option to sample each thread, but not stop them all. That can get a full register snapshot of the ones running in user mode (for which just that may be very informative), and "as much as you can" register data for blocked ones. You might do that for a "threads-only" snapshot and not dump any memory (could be very quick, minimal i/o, useful for flight-recorder, health-monitoring, etc.). Or you might dump memory too, where you are synchronizing against mmap changes, but letting threads run--then the stacks for the blocked ones are complete, even if still-running ones are being overwritten while you dump. (That e.g. might be the right balance for a monitoring sample where you just want to notice the details of threads staying blocked for a long time while minimizing any delays to the highly-active threads.) Conclusions. I've mentioned lots of kinds of flexibility one might like in the core dumper's features. This doesn't mean I expect you to add every bell and whistle I can imagine. It's just to get you thinking, and to advocate for a different way to structure the code that would make it possible to do more different and fancy things eventually. In #1 there are two issues due to using elf_core_dump(). One is mmap/vma synchronization, which you can just solve with mmap_sem. The other is mm->core_state and the whole related set of synchronization problems. In #2 most of the unresolved complexities have to do with the essential synchronization problems of third-party examination. In #3 all the oddities and lacks of flexibility derive from the basic constraint of what elf_core_dump() does. All of that is far simpler IMHO if you take a different approach and do not use elf_core_dump() at all. There is only a little code from there I would really want to reuse/refactor. For a prototype to start with I think it's certainly fine to just copy those few routines, and we can worry later about refactoring to share code with elf_core_dump. For overloading mm->core_state, you just don't do it. Don't touch that, and you don't interact with do_coredump() at all, except inasmuch as it can instigate some threads dying before you stop them (which is always possible anyway). What I'd do is have each thread fill in its own info (prstatus and regsets) directly in the utrace callback. Then once each task is logged as stopped you only need to keep track of them as long as you want them in UTRACE_STOP (if doing a non-stop option, detach them right there). You still have to do the third-party examination when utrace_control(,,UTRACE_STOP) returns zero because it's already stopped (either another debugger or job control stop). But that's a pretty easy case where you know you only have to worry about the SIGKILL races. (It's good enough just to zero the buffers beforehand and ignore errors from the regset calls.) That way you just use the QUIESCE callback. If it's for death, you detach and forget the thread ever existed. If not, you reset your engine with utrace_set_events to zero, collect all the data on yourself, and return UTRACE_STOP. There are no other races to worry about. After that, if threads die, they die, but you aren't looking anyway. You only keep track of them at all so that they stay in UTRACE_STOP, until you call utrace_control(,,UTRACE_DETACH) after the dump (or before, in a non-stop option). That returns -ESRCH if it died and detached already, but you don't care anyway. Core dumping has three components: thread stuff, memory collection, and file writing. I include all the synchronization bits in "thread stuff", which I've outlined an approach for. The memory collection and file writing are pretty well independent of the thread stuff. The memory collection is straightforward and there is just one way to do it (modulo flexibility in elision choices). The file writing is defined by what interface and control semantics you are using to drive the feature. At least for a normal fully-synchronous snapshot, in any interface you have to do the thread stuff first. Before you start reading memory you need to know threads are stopped so they won't touch it, and you need them to call any regset writeback hooks. You can't even take mmap_sem before finishing thread stuff, because if a thread can enter the kernel and might do down_write(), you could deadlock waiting for it to finish and stop while it waits for you to up_read(). So every implementation plan for whatever interface will probably have that in common: first, you do thread stuff, then you take mmap_sem and do memory stuff. Part of my point in bringing up all the flexibility is that I think in the long run what we'll want is to break up the core dump work in the kernel into several pieces that can be reused in a variety of contexts and plug into multiple different interfaces. But we don't have to worry about that for the prototype. For a standalone feature prototype somewhat along the lines of what you've done, one interface idea is attracting my attention. That is a virtual-file "pull" interface, akin to /proc/kcore. So, rather than userland magically poking a "write a file" command, instead userland gets to read a virtual file of core dump contents and any actual i/o writing the data out is userland's business. What I have in mind is to support random-access reads; this gives userland automatic flexibility to just skip over some parts if it wants, and for the core file portions corresponding to memory, this will completely elide fetching those pages. Userland can use normal reads, or shovel the data with splice or sendfile to write a file directly. Later, we can soup up the internals so that splice/sendfile from the virtual file does optimized internal magic to avoid copying the pages. Here's the interface I have in mind: magic file /proc/pid/gcore. When you open the file, this starts trying to stop all the threads. When you first actually read from the file, this blocks until all the thread stuff is done. Then it takes mmap_sem and collects all the phdrs. That is all the information other than actual memory contents, and it's enough to know everything about the file layout. You can collect that info directly on some pages in the core file format; the ehdr and phdrs you collect are all the information you need to do later i/o. (After that you can actually drop mmap_sem and it no longer matters.) Once the notes/headers (including all thread stuff) are ready, then you keep those pages around as long as the file is open. A read call that asks for those initial pages just gets those saved pages. A read call for a larger offset is in the part of the file that corresponds to memory. You can look up that offset in the phdrs you saved (in part of those initial pages) and map from p_offset to p_vaddr, then just use get_user_pages/access_process_vm to read those pages. The only other bookkeeping you need is the list of tasks+engines you have attached; when the virtual file is closed, you detach those engines and clean up. For further fanciness, we can later make it support nonblocking read, poll, and fasync. This lets a fancy user open the file, get a notification when it's ready to read (all threads have stopped and collected register data), and then read when they know it won't block (except for page fault blocks in memory areas). Other fanciness that is probably more important, we can later add an optimized splice_read callback to the virtual file. This can send the saved initial pages and the memory pages from get_user_pages() directly to splice_to_pipe. This makes splice/sendfile calls do single-copy i/o that should go as fast as traditional direct-from-kernel core writing, if not faster. This is only one interface idea, but I think it's got some sex appeal. The main point about organizing the control flow/synchronization plan in this way applies to any sort of interface. Thanks, Roland From srikar at linux.vnet.ibm.com Mon Aug 3 06:49:27 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Mon, 3 Aug 2009 12:19:27 +0530 Subject: gdbstub/uprobes problems: uprobe_unregister with halted target In-Reply-To: <1249085124.5082.83.camel@localhost.localdomain> References: <20090731194622.GC12318@redhat.com> <20090731220849.GD12318@redhat.com> <1249085124.5082.83.camel@localhost.localdomain> Message-ID: <20090803064927.GD27318@linux.vnet.ibm.com> > > > > The target process side is also hung: > > > > zsh D 0000000000000002 3568 1288 1259 0x00000080 > > ffff880078c57b98 0000000000000046 0000000000000000 0000000000011d4a > > ffff88006d4b8000 0000000000000000 ffff880078c57f50 00007fff138b0858 > > ffff88006d4b83b8 000000000000f968 ffff88006d4b83b8 00000000001d5740 > > Call Trace: > > [] ? gdb_uprobe_handler+0x79/0xc2 > > [] ? gdb_uprobe_handler+0x79/0xc2 > > [] ? gdb_uprobe_handler+0x79/0xc2 > > [] __mutex_lock_common+0x207/0x38a > > [] ? gdb_uprobe_handler+0x79/0xc2 > > [] mutex_lock_nested+0x3c/0x41 > > [] gdb_uprobe_handler+0x79/0xc2 > > [] uprobe_report_signal+0x4e5/0x959 > > [] ? lock_release_holdtime+0x2c/0x11d > > [] ? _spin_unlock+0x2b/0x30 > > [] utrace_get_signal+0x33d/0x5bd > > [] ? get_signal_to_deliver+0x4c/0x3b6 > > [] get_signal_to_deliver+0xf6/0x3b6 > > [] ? kvm_clock_read+0x21/0x23 > > [] do_notify_resume+0x89/0x746 > > [] ? __up_read+0x76/0x7f > > [] ? paranoid_userspace+0x39/0x5a > > [] ? trace_hardirqs_on_caller+0x126/0x14a > > [] paranoid_userspace+0x4b/0x5a > > > > and the corresponding function call graph was: > > > > 3854 zsh(1350): uprobe_report_signal action=0x0 engine=0xffff88003ac36078 tsk=0xffff880037d0a470 regs=0xffff880059097f58 info > > 3867 zsh(1350): utrace_attach_pid pid=0xffff880078e8d680 flags=0x1 ops=0xffffffff81443be0 data=0x0 > > 3881 zsh(1350): utrace_attach_task target=0xffff880037d0a470 flags=0x1 ops=0xffffffff81443be0 data=0x0 > > 3890 zsh(1350): matching_engine utrace=0xffff880037d0aad8 flags=0x1 ops=0xffffffff81443be0 data=0x0 > > 3901 zsh(1350): matching_engine return=0xffff880078d190f0 > > 3907 zsh(1350): utrace_attach_task return=0xffff880078d190f0 > > 3914 zsh(1350): put_task_struct t=0xffff880037d0a470 > > 3918 zsh(1350): put_task_struct > > 3923 zsh(1350): utrace_attach_pid return=0xffff880078d190f0 > > I can't think of why utrace_attach_pid() would get called here. utrace_attach_pid is from xol_get_area(). So its clear that this was the first time uprobe_report_signal was called. Also the call to uretprobe_set_trampoline (below) confirms that this was the first time uprobe_report_signal was called. > > > 3931 zsh(1350): uretprobe_set_trampoline uproc=0xffff880075bc77e0 tsk=0xffff880037d0a470 > > 3947 zsh(1350): kzalloc").call size=0x40 flags=? > > 3955 zsh(1350): kzalloc").return return=0xffff88001ec27ee0 > > 3986 zsh(1350): uretprobe_set_trampoline > > 3999 zsh(1350): clear_utrace_quiesce utask=0xffff880078f53290 resume=0x0 > > 4007 zsh(1350): utask_adjust_flags utask=0xffff880078f53290 set=0x0 flags=0x1 > > 4012 zsh(1350): utask_adjust_flags > > 4017 zsh(1350): clear_utrace_quiesce > > 4028 zsh(1350): uprobe_find_probept uproc=0xffff880075bc77e0 vaddr=0x419dd0 > > 4034 zsh(1350): uprobe_find_probept return=0xffff8800377a4248 > > 4041 zsh(1350): gdb_uprobe_handler up=0xffff8800220c1660 regs=0xffff880059097f58 > > 4060 zsh(1350): gdb_uprobe_handler > > 4073 zsh(1350): utask_adjust_flags utask=0xffff880078f53290 set=0x1 flags=0x1 > > 4080 zsh(1350): utrace_set_events_pid pid=0xffff880078e8d680 engine=0xffff88003ac36078 eventmask=0x131d > > 4088 zsh(1350): utrace_set_events target=0xffff880037d0a470 engine=0xffff88003ac36078 events=0x131d > > 4095 zsh(1350): get_utrace_lock target=0xffff880037d0a470 engine=0xffff88003ac36078 attached=0x1 > > 4108 zsh(1350): get_utrace_lock return=0xffff880037d0aad8 > > 4210 zsh(1350): utrace_set_events return=0x0 > > 4215 zsh(1350): utrace_set_events_pid return=0x0 > > 4220 zsh(1350): utask_adjust_flags > > 4227 zsh(1350): uprobe_put_process uproc=0xffff880075bc77e0 in_callback=0x1 > > 4232 zsh(1350): uprobe_put_process return=0x0 > > 4237 zsh(1350): uprobe_report_signal return=0x13 return action from uprobes is 0x13 which is UTRACE_SIGNAL_IGN | UTRACE_SINGLESTEP i.e ignore this signal because it was induced by uprobes and do a singlestep. > > 4242 zsh(1350): finish_callback utrace=0xffff880037d0aad8 report=0xffff880059097d98 engine=0xffff88003ac36078 ret=0x13 > > 4248 zsh(1350): finish_callback return=0x0 > > 4254 zsh(1350): finish_resume_report report=0xffff880059097d98 task=0xffff880037d0a470 utrace=0xffff880037d0aad8 > > 4261 zsh(1350): utrace_reset task=0xffff880037d0a470 utrace=0xffff880037d0aad8 action=0xffff880059097d98 > > 4268 zsh(1350): put_detached_list list=0xffff880059097cc8 > > 4273 zsh(1350): put_detached_list > > 4278 zsh(1350): utrace_reset > > 4284 zsh(1350): utrace_stop task=0xffff880037d0a470 utrace=0xffff880037d0aad8 report=0x0 > > I'm confused here. Is the traced task getting hung in > gdb_uprobe_handler() -- per your call trace -- or utrace_stop() (or > elsewhere) -- per your call graph? So as per my analysis, gdb_utrace_report_signal was called, followed by uprobe_report_signal. Since gdb_utrace_report_signal requested for UTRACE_STOP as resume action for SIGTRAP, the thread got stopped. uprobes was waiting for either the singlestep to occur (or the process to exit/exec or some other event) before it could signal the process to be quiesced. The unregistering thread (as pointed out by Jim) was waiting for the thread to be set to be quiesced before it could complete the unregistering. -- Thanks and Regards Srikar > > > > > So it's as if there may be some sort of conflict between send_sig() > > and unregister_uprobes(), but I'm not sure. Do you have any initial > > advice about what's supposed to work / not work, or what else to > > instrument? > > From info at canal-marketing.com Mon Aug 3 06:55:00 2009 From: info at canal-marketing.com (=?ISO-8859-1?Q?IC_Telecom?=) Date: Mon, 03 Aug 2009 08:55:00 +0200 Subject: Illimite : Communications - Internet - telephones Message-ID: An HTML attachment was scrubbed... URL: From ananth at in.ibm.com Mon Aug 3 08:04:35 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Mon, 3 Aug 2009 13:34:35 +0530 Subject: [PATCH 2/3] Quiesce all threads of a process In-Reply-To: <1249059551.5082.14.camel@localhost.localdomain> References: <20090730095514.GH5232@in.ibm.com> <20090730095656.GJ5232@in.ibm.com> <1249059551.5082.14.camel@localhost.localdomain> Message-ID: <20090803080435.GC4394@in.ibm.com> On Fri, Jul 31, 2009 at 09:59:11AM -0700, Jim Keniston wrote: > > On Thu, 2009-07-30 at 15:26 +0530, Ananth N Mavinakayanahalli wrote: > > > +static u32 core_clone(enum utrace_resume_action action, > ... > > + /* > > + * -EINPROGRESS => thread on the way to quiesce > > + * -EALREADY => we may be racing with attach_utrace_engines > > + * and it may already have attached an engine for us. > > + */ > > + if (ret && ((ret != -EINPROGRESS) || (ret != -EALREADY))) { > > ((ret != -EINPROGRESS) || (ret != -EALREADY)) ??? > Assuming EINPROGRESS != EALREADY, this test is always true. I think you > want && here, in which case you can dispense with most of the parens. Yup, you are right. I'll fix it. > ... > > +/* > > + * Process exec()ing. Abort and exit from here > > + * > > + * XXX: > > + * a. Is this necessary? > > I think it's a good idea to handle the exec case. But since dumping > core for an exec-ing process is a rather bizarre thing to attempt, you > can probably handle it however is most convenient for you. Yes, in light of Roland's detailed description, all these will change for sure. > > + * b. Are we safe here wrt the core dump being in progress? > > Assuming all threads are quiesced before you start your actual core > dump, there's no way one of them can exec while you're dumping. Right. > > + */ > > +static u32 core_exec(enum utrace_resume_action action, > > + struct utrace_engine *engine, struct task_struct *task, > > + const struct linux_binfmt *fmt, const struct linux_binprm *bprm, > > + struct pt_regs *regs) > > +... > > + > > +static struct core_proc *attach_utrace_engines(struct task_struct *task) > > +{ > ... > > + /* > > + * -EINPROGRESS => we are on our way to quiesce. > > + * -EEXIST => we may be racing with core_clone and it has > > + * already attached an engine for us. > > + */ > > + if (ret && ((ret != EINPROGRESS) || (ret != -EALREADY))) > > s/||/&&/ -- as above. Agreed. Ananth From oleg at redhat.com Mon Aug 3 14:33:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 3 Aug 2009 16:33:31 +0200 Subject: [PATCH 5/6] finish_utrace_stop: check ->stopped lockless In-Reply-To: <20090802002225.89D534C87C@magilla.sf.frob.com> References: <20090731010656.GA8074@redhat.com> <20090802002225.89D534C87C@magilla.sf.frob.com> Message-ID: <20090803143331.GA6050@redhat.com> On 08/01, Roland McGrath wrote: > > > finish_utrace_stop() can check ->stopped lockless. It was set by us, > > we can't miss it. > > We enter utrace_stop() for some stop. Either then or later, a group jctl > stop finishes and sets SIGNAL_STOP_STOPPED. Later, utrace_wakeup() sees > that and we switch to TASK_STOPPED after clearing ->stopped. We stay in > jctl stop for a few days. > > Some new debugger comes along with utrace_control(,,UTRACE_STOP) and > utrace_do_stop() switches us to TASK_TRACED after setting ->stopped. > Meanwhile, SIGCONT is coming along and clearing SIGNAL_STOP_STOPPED > (sibling threads run again, etc.). Now the debugger calls > utrace_control(,,UTRACE_RESUME), so utrace_wakeup clears ->stopped and > wakes us up. > > Now ->stopped was just an instant ago set and then cleared on the other > CPU and we are running. Are we really sure that we see it as clear rather > than set? Of course, we can have the false positive. Even simpler: by the time finish_utrace_stop() takes utrace->lock the tracer can clear ->stopped even if it was really set after schedule(). But I think we do not care. What we do care is: ->stopped must be F after finish_utrace_stop(), whoever checks it under utrace->lock. And I think this must be true. If ->stopped was ever cleared before finish_utrace_stop(), nobody can set it again in such a way that we can miss it. when utrace_do_stop() sets ->stopped, we hold ->siglock, this means we can't race with SIGCONT/SIGKILL. If the signal somes after that, we can rely on rq->lock, both try_to_wake_up() and schedule() take this lock, it should act as a barrier. I think. Perhaps it makes sense to move utrace_stop()->recalc_sigpending() code up, before finish_utrace_stop(). This way it would be a bit clearer why we can't race with signals. BTW, I think that finish_utrace_stop() doesn't need ->siglock to check the pending SIGKILL. Anyway, this change is very minor. The only reason I sent this patch is that I spent some time trying to understand which races this unconditional spin_lock(&utrace->lock) tries to close. > But I think that I can even worry about this is a good > indicator that we'd probably be happier if we can indeed get rid of > ->stopped altogether. I think you are right, and ->stopped _can_ go away. But, as a devil's advocate, I'd like to give a couple of weak arguments against this change. - Currently, if we see ->stopped == T under utrace->lock we know that the tracee can do nothing interesting from utrace pov. It can't be waked up by utrace_wakeup(). If the tracee is killed it must take ->lock to clear ->stopped before it can do anything else. If we remove ->stopped, we can't rely on TASK_TRACED in the same manner. For example, a killed tracee can can call utrace_report_jctl()->REPORT() while utrace thinks it is stopped. - The exiting task with _UTRACE_DEATH_EVENTS can be considered as quiescent. But, without ->stopped, looking at this task we can't know if some engine wants this task to be stopped. IOW, if we see such a task we can't figure out was utrace_do_stop() called or not. - I _think_ that ->stopped makes the code a bit more readable and understandable. More "explicit". But this is really subjective. On the other hand I agree with your arguments. And, as you pointed out, we can kill utrace_finish_jctl(). In short - I do not know. Oleg. From oleg at redhat.com Mon Aug 3 16:14:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 3 Aug 2009 18:14:46 +0200 Subject: [PATCH 3/6] utrace_do_stop: s/STOPPED/TRACED/ to protect against SIGCONT In-Reply-To: <20090802000143.9F0684C800@magilla.sf.frob.com> References: <20090731010651.GA8064@redhat.com> <20090802000143.9F0684C800@magilla.sf.frob.com> Message-ID: <20090803161446.GB6050@redhat.com> On 08/01, Roland McGrath wrote: > > I've merged these (up to 5/6 so far). > > Now I'm looking at all the uses of ->stopped. > > * utrace_set_events > could test task_is_stopped_or_traced() || ->exit_state > > * utrace_control: > could test task_is_traced() || > ->exit_state && !(->utrace_flags & _UTRACE_DEATH_EVENTS) > (or let utrace_do_stop test the latter) > > * finish_utrace_stop > detects signal_wake_up(,1) (SIGKILL) > > (And the rest are just the bookkeeping to keep it set/cleared.) > > So I think it's now true that the only thing ->stopped is buying us is that > finish_utrace_stop test. Do you agree? Yes, mostly, see my another reply. > Perhaps we can just replace that with __fatal_signal_pending Ah, I think in any case __fatal_signal_pending() is tidier for finish_utrace_stop(). Oleg. From jkenisto at us.ibm.com Mon Aug 3 18:10:00 2009 From: jkenisto at us.ibm.com (Jim Keniston) Date: Mon, 03 Aug 2009 11:10:00 -0700 Subject: gdbstub/uprobes problems: uprobe_unregister with halted target In-Reply-To: <20090803064927.GD27318@linux.vnet.ibm.com> References: <20090731194622.GC12318@redhat.com> <20090731220849.GD12318@redhat.com> <1249085124.5082.83.camel@localhost.localdomain> <20090803064927.GD27318@linux.vnet.ibm.com> Message-ID: <1249323000.5397.19.camel@localhost.localdomain> On Mon, 2009-08-03 at 12:19 +0530, Srikar Dronamraju wrote: > > ... > > > > > > and the corresponding function call graph was: > > > > > > 3854 zsh(1350): uprobe_report_signal action=0x0 engine=0xffff88003ac36078 tsk=0xffff880037d0a470 regs=0xffff880059097f58 info > > > 3867 zsh(1350): utrace_attach_pid pid=0xffff880078e8d680 flags=0x1 ops=0xffffffff81443be0 data=0x0 > > > 3881 zsh(1350): utrace_attach_task target=0xffff880037d0a470 flags=0x1 ops=0xffffffff81443be0 data=0x0 > > > 3890 zsh(1350): matching_engine utrace=0xffff880037d0aad8 flags=0x1 ops=0xffffffff81443be0 data=0x0 > > > 3901 zsh(1350): matching_engine return=0xffff880078d190f0 > > > 3907 zsh(1350): utrace_attach_task return=0xffff880078d190f0 > > > 3914 zsh(1350): put_task_struct t=0xffff880037d0a470 > > > 3918 zsh(1350): put_task_struct > > > 3923 zsh(1350): utrace_attach_pid return=0xffff880078d190f0 > > > > I can't think of why utrace_attach_pid() would get called here. > > utrace_attach_pid is from xol_get_area(). So its clear that this was the > first time uprobe_report_signal was called. Also the call to > uretprobe_set_trampoline (below) confirms that this was the first time > uprobe_report_signal was called. Yes, indeed. ... > > > So as per my analysis, gdb_utrace_report_signal was called, followed by > uprobe_report_signal. Since gdb_utrace_report_signal requested for > UTRACE_STOP as resume action for SIGTRAP, the thread got stopped. > uprobes was waiting for either the singlestep to occur (or the process to > exit/exec or some other event) before it could signal the process to be > quiesced. Uprobes attempts to handle this situation. Before returning (UTRACE_SINGLESTEP | UTRACE_SIGNAL_IGN), uprobe_report_signal() registers to be notified of quiesce events. If report_signal for some other engine (e.g., gdbstub's) requests a UTRACE_STOP, that'll override uprobe_report_signal()'s UTRACE_SINGLESTEP. But uprobe_report_quiesce() should get called as a result and re-assert UTRACE_SINGLESTEP. Assuming gdbstub's report_quiesce callback eventually returns something other than UTRACE_STOP, the UTRACE_SINGLESTEP should take effect. That was my thinking, anyway. I can't guarantee that it actually works that way. > ... > > -- > Thanks and Regards > Srikar Jim From roland at redhat.com Mon Aug 3 19:06:58 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 3 Aug 2009 12:06:58 -0700 (PDT) Subject: [PATCH 5/6] finish_utrace_stop: check ->stopped lockless In-Reply-To: Oleg Nesterov's message of Monday, 3 August 2009 16:33:31 +0200 <20090803143331.GA6050@redhat.com> References: <20090731010656.GA8074@redhat.com> <20090802002225.89D534C87C@magilla.sf.frob.com> <20090803143331.GA6050@redhat.com> Message-ID: <20090803190658.D643641063@magilla.sf.frob.com> > Of course, we can have the false positive. Even simpler: by the time > finish_utrace_stop() takes utrace->lock the tracer can clear ->stopped > even if it was really set after schedule(). Right. It didn't even occur to me that the only scenario I thought of was a false positive. I was just thinking through the statement you made about why lockless was OK ("we will have set it ourselves"). > But I think we do not care. What we do care is: ->stopped must be F > after finish_utrace_stop(), whoever checks it under utrace->lock. We do care about a false positive if it makes finish_utrace_stop() hit its WARN_ON and return true when there was no SIGKILL. > when utrace_do_stop() sets ->stopped, we hold ->siglock, this means > we can't race with SIGCONT/SIGKILL. If the signal somes after that, > we can rely on rq->lock, both try_to_wake_up() and schedule() take > this lock, it should act as a barrier. I think. Ok. If we are in fact relying on any implicit barrier semantics like that, we should have a clear comment about it. > Perhaps it makes sense to move utrace_stop()->recalc_sigpending() > code up, before finish_utrace_stop(). This way it would be a bit > clearer why we can't race with signals. Ok. I'm not quite seeing just now why this is clearer. But if you have a patch with comments in it, I will probably understand why. > BTW, I think that finish_utrace_stop() doesn't need ->siglock to > check the pending SIGKILL. Shouldn't one always hold siglock to use task->pending at all? > Anyway, this change is very minor. The only reason I sent this patch > is that I spent some time trying to understand which races this > unconditional spin_lock(&utrace->lock) tries to close. Good! Indeed I don't want to waste too much time on minor things, and we can always clean up more later. But it is crucial that you are thinking thoroughly about all the locking and race questions in the code, so that is always time well spent. > I think you are right, and ->stopped _can_ go away. But, as a devil's > advocate, I'd like to give a couple of weak arguments against this > change. Sure! We want to go whichever way makes the code overall easiest to follow, review, and be convinced it's right. > - Currently, if we see ->stopped == T under utrace->lock we > know that the tracee can do nothing interesting from utrace > pov. It can't be waked up by utrace_wakeup(). If the tracee > is killed it must take ->lock to clear ->stopped before it > can do anything else. Right. My original thinking was that it must always get into utrace_get_signal() right then, and that would be responsible for any synchronization that mattered. > If we remove ->stopped, we can't rely on TASK_TRACED in the > same manner. For example, a killed tracee can can call > utrace_report_jctl()->REPORT() while utrace thinks it is > stopped. You mean the tracehook_notify_jctl(why, CLD_CONTINUED) case, right? That is literally the only thing that happens after do_signal_stop() wakes up and before utrace_get_signal() is called. I wonder if it might not make sense anyway to suppress this for the SIGKILL case. Not just the tracing, but the entire CLD_CONTINUED notification. A parent doesn't really need a SIGCHLD,CLD_CONTINUED immediately followed by a SIGCHLD,CLD_KILLED. OTOH, there is still the general point. utrace_get_signal() doesn't take the utrace lock unconditionally, and I don't think we want it to. Even if the only thing that happens is dequeuing SIGKILL, then that could still get to utrace_report_exit(). > - The exiting task with _UTRACE_DEATH_EVENTS can be considered ^dead/dying ^out > as quiescent. But, without ->stopped, looking at this task we > can't know if some engine wants this task to be stopped. IOW, > if we see such a task we can't figure out was utrace_do_stop() > called or not. (I try to reserve "exiting" for PF_EXITING and "dying" for "running with ->exit_state set", because the difference is important.) Who cares? There is no meaning to UTRACE_STOP for a dying or dead task. It counts as quiescent for purposes of utrace_control knowing what it can do, that's all. If it's not quiescent yet, it won't ever "stop", it will just finish dying (i.e. report_death callbacks will finish). > - I _think_ that ->stopped makes the code a bit more readable and > understandable. More "explicit". But this is really subjective. Ok. I'll leave it to you. My first reaction was just that fewer state bits means less bookkeeping to convince oneself is correct, so easier to read in that way. But it's not a strong opinion. > On the other hand I agree with your arguments. And, as you pointed out, > we can kill utrace_finish_jctl(). > > In short - I do not know. I don't either. Your first point above is fairly compelling. OTOH we can just keep utrace_finish_jctl() and have it and finish_utrace_stop() just always take the utrace lock purely to synchronize (and then drop it without changing anything). Then we'd have the invariant that both the task itself going into or out of TASK_TRACED and the waker always hold the utrace lock, without ->stopped. Thus (leaving aside the dying task issue) TASK_TRACED gives all the guarantees you cited for ->stopped. Thanks, Roland From oleg at redhat.com Mon Aug 3 23:22:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 4 Aug 2009 01:22:53 +0200 Subject: utrace_ptrace && task->ptrace In-Reply-To: <20090724230649.8FD1C80563@magilla.sf.frob.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> <20090723190234.GA12037@redhat.com> <20090724230649.8FD1C80563@magilla.sf.frob.com> Message-ID: <20090803232253.GA5682@redhat.com> On 07/24, Roland McGrath wrote: > > > For example, wait_consider_task(). Even some tracehooks, say, > > tracehook_notify_death() need task_is_ptraced(). > > Not "some", just that one, right? Not just one. tracehook_tracer_task, tracehook_notify_jctl. But, > So these are all really the same one > thing: ptrace interfering with normal parent wait/SIGCHLD. yes, they are the same thing actually. > So I'd do: > > static inline bool tracehook_inhibit_wait(struct task_struct *task) > { > return task->utrace_flags && utrace_inhibit_wait(task); > } > > and then utrace_inhibit_wait can look at a bit we keep in struct utrace or > something like that. I think we might be able to get away with unlocked > checks of that bit in wait, if we're sure that we'll do an extra > wake_up_parent after detach or whatnot. Yes, I thought about something like this too. The problem is, I can't imagine all details now. And. I think it is better to make the first working version as simple/small as possible. So. For the first version of CONFIG_PTRACE_UTRACE I'd suggest to use ->ptrace to keep the single bit, PT_PTRACED (well, PT_PTRACE_CAP too). All other PT_ bits should go into engine->data. Also. Either we have to add a lot of #ifdef's into tracehook.h, or we can add a single #ifdef into task_ptrace() (like your utrace-ptrace.patch does). In the last case, do you think something like below makes sense? is_task_ptraced() - means the same with or without utrace task_ptrace() - returns 0 if CONFIG_UTRACE Or we can start with reverting 5cb11446892833e50970fb2277a9f7563b0a8bd3 I regret about this patch now (and now I understand why you were not very happy with this change ;). But this patch was needed for child-data cleanups. However, I think we should forget about these cleanups for now. In any case, we need some changes, and the patch should be sent separately, before re-sending the updated version of utrace, afaics. Oleg. --- WAIT/include/linux/ptrace.h~1_IS_PTRACED 2009-06-19 01:12:47.000000000 +0200 +++ WAIT/include/linux/ptrace.h 2009-08-03 21:49:19.000000000 +0200 @@ -120,6 +120,11 @@ static inline void ptrace_unlink(struct int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data); int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data); +static inline bool is_task_ptraced(struct task_struct *task) +{ + return task->ptrace != 0; +} + /** * task_ptrace - return %PT_* flags that apply to a task * @task: pointer to &task_struct in question --- WAIT/include/linux/tracehook.h~1_IS_PTRACED 2009-06-19 01:12:47.000000000 +0200 +++ WAIT/include/linux/tracehook.h 2009-08-03 22:57:38.000000000 +0200 @@ -63,7 +63,7 @@ struct linux_binprm; */ static inline int tracehook_expect_breakpoints(struct task_struct *task) { - return (task_ptrace(task) & PT_PTRACED) != 0; + return task_ptrace(task) != 0; } /* @@ -73,7 +73,7 @@ static inline void ptrace_report_syscall { int ptrace = task_ptrace(current); - if (!(ptrace & PT_PTRACED)) + if (!ptrace) return; ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); @@ -148,9 +148,8 @@ static inline void tracehook_report_sysc static inline int tracehook_unsafe_exec(struct task_struct *task) { int unsafe = 0; - int ptrace = task_ptrace(task); - if (ptrace & PT_PTRACED) { - if (ptrace & PT_PTRACE_CAP) + if (is_task_ptraced(task)) { + if (task->ptrace & PT_PTRACE_CAP) unsafe |= LSM_UNSAFE_PTRACE_CAP; else unsafe |= LSM_UNSAFE_PTRACE; @@ -171,7 +170,7 @@ static inline int tracehook_unsafe_exec( */ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk) { - if (task_ptrace(tsk) & PT_PTRACED) + if (is_task_ptraced(tsk)) return rcu_dereference(tsk->parent); return NULL; } @@ -195,7 +194,7 @@ static inline void tracehook_report_exec struct pt_regs *regs) { if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && - unlikely(task_ptrace(current) & PT_PTRACED)) + unlikely(task_ptrace(current)) send_sig(SIGTRAP, current, 0); } @@ -379,7 +378,7 @@ static inline void tracehook_signal_hand const struct k_sigaction *ka, struct pt_regs *regs, int stepping) { - if (stepping) + if (task_ptrace(current) && stepping) ptrace_notify(SIGTRAP); } @@ -396,7 +395,7 @@ static inline void tracehook_signal_hand static inline int tracehook_consider_ignored_signal(struct task_struct *task, int sig) { - return (task_ptrace(task) & PT_PTRACED) != 0; + return task_ptrace(task) != 0; } /** @@ -415,7 +414,7 @@ static inline int tracehook_consider_ign static inline int tracehook_consider_fatal_signal(struct task_struct *task, int sig) { - return (task_ptrace(task) & PT_PTRACED) != 0; + return task_ptrace(task) != 0; } /** @@ -478,7 +477,7 @@ static inline int tracehook_get_signal(s */ static inline int tracehook_notify_jctl(int notify, int why) { - return notify || (current->ptrace & PT_PTRACED); + return notify || is_task_ptraced(current); } #define DEATH_REAP -1 @@ -502,7 +501,7 @@ static inline int tracehook_notify_death void **death_cookie, int group_dead) { if (task_detached(task)) - return task->ptrace ? SIGCHLD : DEATH_REAP; + return is_task_ptraced(task) ? SIGCHLD : DEATH_REAP; /* * If something other than our normal parent is ptracing us, then @@ -512,7 +511,7 @@ static inline int tracehook_notify_death if (thread_group_empty(task) && !ptrace_reparented(task)) return task->exit_signal; - return task->ptrace ? SIGCHLD : DEATH_DELAYED_GROUP_LEADER; + return is_task_ptraced(task) ? SIGCHLD : DEATH_DELAYED_GROUP_LEADER; } /** --- WAIT/kernel/ptrace.c~1_IS_PTRACED 2009-07-01 20:52:58.000000000 +0200 +++ WAIT/kernel/ptrace.c 2009-08-03 22:56:36.000000000 +0200 @@ -95,7 +95,7 @@ int ptrace_check_attach(struct task_stru * be changed by us so it's not changing right after this. */ read_lock(&tasklist_lock); - if ((child->ptrace & PT_PTRACED) && child->parent == current) { + if (child->ptrace && child->parent == current) { ret = 0; /* * child->sighand can't be NULL, release_task() --- WAIT/kernel/exit.c~1_IS_PTRACED 2009-07-02 20:19:55.000000000 +0200 +++ WAIT/kernel/exit.c 2009-08-03 22:41:19.000000000 +0200 @@ -754,7 +754,7 @@ static void reparent_leader(struct task_ p->exit_signal = SIGCHLD; /* If it has exited notify the new parent about this child's death. */ - if (!task_ptrace(p) && + if (!is_task_ptraced(p) && p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) { do_notify_parent(p, p->exit_signal); if (task_detached(p)) { @@ -781,7 +781,7 @@ static void forget_original_parent(struc do { t->real_parent = reaper; if (t->parent == father) { - BUG_ON(task_ptrace(t)); + BUG_ON(is_task_ptraced(t)); t->parent = t->real_parent; } if (t->pdeath_signal) @@ -1492,7 +1492,7 @@ static int wait_consider_task(struct wai return 0; } - if (likely(!ptrace) && unlikely(task_ptrace(p))) { + if (likely(!ptrace) && unlikely(is_task_ptraced(p))) { /* * This child is hidden by ptrace. * We aren't allowed to see it now, but eventually we will. --- WAIT/kernel/signal.c~1_IS_PTRACED 2009-08-01 02:21:27.000000000 +0200 +++ WAIT/kernel/signal.c 2009-08-03 22:42:20.000000000 +0200 @@ -1398,7 +1398,7 @@ int do_notify_parent(struct task_struct /* do_notify_parent_cldstop should have been called instead. */ BUG_ON(task_is_stopped_or_traced(tsk)); - BUG_ON(!task_ptrace(tsk) && + BUG_ON(!is_task_ptraced(tsk) && (tsk->group_leader != tsk || !thread_group_empty(tsk))); info.si_signo = sig; @@ -1437,7 +1437,7 @@ int do_notify_parent(struct task_struct psig = tsk->parent->sighand; spin_lock_irqsave(&psig->siglock, flags); - if (!task_ptrace(tsk) && sig == SIGCHLD && + if (!is_task_ptraced(tsk) && sig == SIGCHLD && (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN || (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) { /* @@ -1474,7 +1474,7 @@ static void do_notify_parent_cldstop(str struct task_struct *parent; struct sighand_struct *sighand; - if (task_ptrace(tsk)) + if (is_task_ptraced(tsk)) parent = tsk->parent; else { tsk = tsk->group_leader; From oleg at redhat.com Mon Aug 3 23:53:06 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 4 Aug 2009 01:53:06 +0200 Subject: [PATCH -mm] introduce tracehook_finish_jctl() helper In-Reply-To: <20090801233207.E1FEB4C7FF@magilla.sf.frob.com> References: <20090729020139.GA7381@redhat.com> <20090729155007.f4f5a793.akpm@linux-foundation.org> <20090801233207.E1FEB4C7FF@magilla.sf.frob.com> Message-ID: <20090803235306.GA6821@redhat.com> On 08/01, Roland McGrath wrote: > > > Confused. This patch has no effect. > > Indeed, the three patches changing do_signal_stop() have no immediate > material effect. They all just clean up the code and prepare the hooks > that utrace (or something like it) needs to make tracing stops mesh well > with job control stops. I'd thought it might be simpler for review to just > roll these three together and send you a single patch to replace > signals-tracehook_notify_jctl-change.patch; but Oleg decided to keep it > sliced smaller. But let me repeat, I would be happy if these 2 new patches are folded into signals-tracehook_notify_jctl-change.patch. Oleg. From roland at redhat.com Tue Aug 4 02:11:23 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 3 Aug 2009 19:11:23 -0700 (PDT) Subject: utrace_ptrace && task->ptrace In-Reply-To: Oleg Nesterov's message of Tuesday, 4 August 2009 01:22:53 +0200 <20090803232253.GA5682@redhat.com> References: <20090716055948.GA31266@redhat.com> <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> <20090723190234.GA12037@redhat.com> <20090724230649.8FD1C80563@magilla.sf.frob.com> <20090803232253.GA5682@redhat.com> Message-ID: <20090804021123.581B241063@magilla.sf.frob.com> > > Not "some", just that one, right? > > Not just one. tracehook_tracer_task, tracehook_notify_jctl. Ah. tracer_task is an outlier we can think about separately a little later. The notify_jctl case is another in the same bag of wait/SIGCHLD things that I had in mind. > The problem is, I can't imagine all details now. And. I think it is better > to make the first working version as simple/small as possible. Sure, incremental steps are fine. > So. For the first version of CONFIG_PTRACE_UTRACE I'd suggest to use > ->ptrace to keep the single bit, PT_PTRACED (well, PT_PTRACE_CAP too). > All other PT_ bits should go into engine->data. Ok. > Also. Either we have to add a lot of #ifdef's into tracehook.h, or we > can add a single #ifdef into task_ptrace() (like your utrace-ptrace.patch > does). In the last case, do you think something like below makes sense? There is no plan for #ifdef's. What hch et al upstream told us is that there should be only one ptrace implementation, no options (and so utrace has to be rock solid, which is why I'm getting you to do all the hard parts ;-). AFAIK this is our plan now. Old ptrace goes away and only the utrace-based implementation exists at the end. (It's not my idea. But I tried it with the option before and had no luck whatsoever getting utrace merged that way, so I'm trying to do what I was told most recently.) The sole original purpose of task_ptrace() was for conditionalizing the things in tracehook.h that can be replaced by utrace hooks. Now all those ptrace checks in tracehook.h just go entirely. The only ptrace things that remain, either as permanent special cases, or until we address those needs with something new in utrace, are: tracehook_unsafe_exec tracehook_tracer_task and the wait-interference cases. (That's why those didn't use the wrapper.) > Or we can start with reverting 5cb11446892833e50970fb2277a9f7563b0a8bd3 > I regret about this patch now (and now I understand why you were not > very happy with this change ;). Yes, well. There's always more cleaning up to do later. > But this patch was needed for child-data cleanups. However, I think we > should forget about these cleanups for now. What?!? The whole point of tracee data structure cleanup was to fit it cleanly with utrace. i.e., to have a thing to hang off engine->data. I don't understand why you'd want to abandon that now. > In any case, we need some changes, and the patch should be sent separately, > before re-sending the updated version of utrace, afaics. I'd always expected that a large number of the ptrace cleanup patches would precede utrace being merged. That's why you were working on them first. Thanks, Roland From srikar at linux.vnet.ibm.com Tue Aug 4 14:23:05 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Tue, 4 Aug 2009 19:53:05 +0530 Subject: gdbstub/uprobes problems: uprobe_unregister with halted target In-Reply-To: <1249323000.5397.19.camel@localhost.localdomain> References: <20090731194622.GC12318@redhat.com> <20090731220849.GD12318@redhat.com> <1249085124.5082.83.camel@localhost.localdomain> <20090803064927.GD27318@linux.vnet.ibm.com> <1249323000.5397.19.camel@localhost.localdomain> Message-ID: <20090804142305.GB27203@linux.vnet.ibm.com> * Jim Keniston [2009-08-03 11:10:00]: > > > > > > So as per my analysis, gdb_utrace_report_signal was called, followed by > > uprobe_report_signal. Since gdb_utrace_report_signal requested for > > UTRACE_STOP as resume action for SIGTRAP, the thread got stopped. > > uprobes was waiting for either the singlestep to occur (or the process to > > exit/exec or some other event) before it could signal the process to be > > quiesced. > > Uprobes attempts to handle this situation. Before returning > (UTRACE_SINGLESTEP | UTRACE_SIGNAL_IGN), uprobe_report_signal() > registers to be notified of quiesce events. If report_signal for some > other engine (e.g., gdbstub's) requests a UTRACE_STOP, that'll override > uprobe_report_signal()'s UTRACE_SINGLESTEP. But uprobe_report_quiesce() > should get called as a result and re-assert UTRACE_SINGLESTEP. Assuming > gdbstub's report_quiesce callback eventually returns something other > than UTRACE_STOP, the UTRACE_SINGLESTEP should take effect. > > That was my thinking, anyway. I can't guarantee that it actually works > that way. > If we refer to the discussion between you and Roland https://www.redhat.com/archives/utrace-devel/2008-July/msg00063.html I understand this as: If quiesce event is requested on a stopped thread, then report_quiesce (in this case uprobe_report_quiesce) will only be called when the thread starts to run but before it reaches user space. It also seems quiesce event on stopped threads is only useful, if one or more engines request a UTRACE_REPORT or UTRACE_INTERRUPT. However do correct me if I have misunderstood your discussion. Additionally please refer my mail to utrace-devel here. https://www.redhat.com/archives/utrace-devel/2009-March/msg00006.html I had reported that on resume, I have noticied that singlestep being ignored. So even if the program was resumed, there are chances that singlestep will not occur, resulting in the program existing prematurely. -- Thanks and Regards Srikar From oleg at redhat.com Tue Aug 4 23:24:18 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 5 Aug 2009 01:24:18 +0200 Subject: [PATCH 5/6] finish_utrace_stop: check ->stopped lockless In-Reply-To: <20090803190658.D643641063@magilla.sf.frob.com> References: <20090731010656.GA8074@redhat.com> <20090802002225.89D534C87C@magilla.sf.frob.com> <20090803143331.GA6050@redhat.com> <20090803190658.D643641063@magilla.sf.frob.com> Message-ID: <20090804232418.GA26768@redhat.com> On 08/03, Roland McGrath wrote: > > > But I think we do not care. What we do care is: ->stopped must be F > > after finish_utrace_stop(), whoever checks it under utrace->lock. > > We do care about a false positive if it makes finish_utrace_stop() hit its > WARN_ON and return true when there was no SIGKILL. Yes sure. Now I see I misunderstood your previous email. I think that this type of false positive is not possible. Please see below. > > when utrace_do_stop() sets ->stopped, we hold ->siglock, this means > > we can't race with SIGCONT/SIGKILL. If the signal somes after that, > > we can rely on rq->lock, both try_to_wake_up() and schedule() take > > this lock, it should act as a barrier. I think. > > Ok. If we are in fact relying on any implicit barrier semantics like > that, we should have a clear comment about it. Ah. I guess I just added the unnecessary confusion. Indeed, we should not rely on any implicit barrier semantics with rq->lock. What I meant, we can rely on the fact that any wakeup (try_to_wakeup() actually) must be a barrier wrt schedule(). IOW, if we do VAR = 1; try_to_wake_up(TASK); Then TASK can safely do set_current_state(); schedule(); BUG_ON(VAR != 1); this is true even if the task does not sleep, in case it is woken before it enters schedule(). So. If utrace_control() path changes ->stopped and wakes up the tracee, it must see the correct value of ->stopped. This is simple. But what if the tracee is woken by CONT/KILL? Should the tracee see the last change in ->stopped? The signal can race with utrace_wakeup() or utrace_do_stop(), there are a lot of cases when the woken tracee can look at ->stopped while it is changed by utrace. But I think all we need is to be sure that: - if ->stopped == T, we have a pending SIGKILL If we were woken by SIGCONT which comes right after utrace_wakeup() does s/TRACED/STOPPED/, I think we must see the result of "->stopped = 0" in utrace_wakeup(). Both utrace_wakeup() and signal_wake_up() take ->siglock, the memory change in ->stopped must be visible to utrace_wakeup() and the wakee. - If we were killed, we must see ->stopped == T _unless_ utrace_wakeup() is in progress or we are already woken from utrace pov. Now we should worry about SIGKILL racing with utrace_do_stop(). Again, both take ->siglock, etc. But in short, I can't understand how utrace->lock can really help, given that a signal changes task's state without this lock. It can only help to avoid the races with utrace playing with ->stopped in parallel, but I see nothing dangerous here. > > BTW, I think that finish_utrace_stop() doesn't need ->siglock to > > check the pending SIGKILL. > > Shouldn't one always hold siglock to use task->pending at all? Why? It only checks the bit. Note that fatal_signal_pending() is used lockless. But this discussion makes me wonder, what report->killed and utrace_stop's returned value buy us? Can't we kill report->killed and make utrace_stop() return void? With or without this patch. Suppose that (say) utrace_report_syscall_entry() does utrace_stop() and sleeps in TASK_TRACED. Another thread starts the group stop and sets SIGNAL_STOP_STOPPED. utrace_wakeup() clears ->stopped, notices SIGNAL_STOP_STOPPED and doesn't wake up. Now, we can sleep a long time. Then SIGKILL kills us, but finish_utrace_stop() returns false. Afaics, only utrace_get_signal() uses report.kill, and only utrace_report_syscall_entry() uses the result of utrace_stop(). Both can just check fatal_signal_pending(). > > - Currently, if we see ->stopped == T under utrace->lock we > > know that the tracee can do nothing interesting from utrace > > pov. It can't be waked up by utrace_wakeup(). If the tracee > > is killed it must take ->lock to clear ->stopped before it > > can do anything else. > > Right. My original thinking was that it must always get into > utrace_get_signal() right then, and that would be responsible for any > synchronization that mattered. > > > If we remove ->stopped, we can't rely on TASK_TRACED in the > > same manner. For example, a killed tracee can can call > > utrace_report_jctl()->REPORT() while utrace thinks it is > > stopped. > > You mean the tracehook_notify_jctl(why, CLD_CONTINUED) case, right? Not sure. utrace_get_signal() can call ->report_signal() before it takes utrace->lock. > I wonder if it might not make sense anyway to suppress this for the > SIGKILL case. Not just the tracing, but the entire CLD_CONTINUED > notification. A parent doesn't really need a SIGCHLD,CLD_CONTINUED > immediately followed by a SIGCHLD,CLD_KILLED. Heh. Actually, I was wrong. utrace_report_jctl() is not possible if the tracee is killed. complete_signal(SIGKILL) sets ->flags = SIGNAL_GROUP_EXIT. > > - The exiting task with _UTRACE_DEATH_EVENTS can be considered > ^dead/dying ^out > > as quiescent. But, without ->stopped, looking at this task we > > can't know if some engine wants this task to be stopped. IOW, > > if we see such a task we can't figure out was utrace_do_stop() > > called or not. > > (I try to reserve "exiting" for PF_EXITING and "dying" for "running > with ->exit_state set", because the difference is important.) > > Who cares? Agreed. > OTOH we can just keep utrace_finish_jctl() and have it and > finish_utrace_stop() just always take the utrace lock purely > to synchronize (and then drop it without changing anything). or we can just do spin_unlock_wait(). Anyway, I believe that this change, even if good, is low priority. I mean, it doesn't immediately makes possible other improvements, afaics. But this all is up to you. Oleg. From oleg at redhat.com Tue Aug 4 23:54:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 5 Aug 2009 01:54:58 +0200 Subject: utrace_ptrace && task->ptrace In-Reply-To: <20090804021123.581B241063@magilla.sf.frob.com> References: <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> <20090723190234.GA12037@redhat.com> <20090724230649.8FD1C80563@magilla.sf.frob.com> <20090803232253.GA5682@redhat.com> <20090804021123.581B241063@magilla.sf.frob.com> Message-ID: <20090804235458.GB26768@redhat.com> On 08/03, Roland McGrath wrote: > > > So. For the first version of CONFIG_PTRACE_UTRACE I'd suggest to use > > ->ptrace to keep the single bit, PT_PTRACED (well, PT_PTRACE_CAP too). > > All other PT_ bits should go into engine->data. > > Ok. Actually the very first "for utrace-devel only" version should be just your utrace-ptrace.patch + attach/detach fixes. Not that I can verify this, but I hope that ptrace_utrace_ops's methods are more or less right. (but of course, we should recheck them as much is possible). Than we can move some things into engine->data. Right now my only concern is attach/detach, and the only method which needs the immediate attention is ptrace_resumed() which (afaics wrongly) does the "deferred" detach. > > Also. Either we have to add a lot of #ifdef's into tracehook.h, or we > > can add a single #ifdef into task_ptrace() (like your utrace-ptrace.patch > > does). In the last case, do you think something like below makes sense? > > There is no plan for #ifdef's. What hch et al upstream told us is that > there should be only one ptrace implementation, no options (and so utrace > has to be rock solid, which is why I'm getting you to do all the hard parts > ;-). AFAIK this is our plan now. Old ptrace goes away and only the > utrace-based implementation exists at the end. Hmm. Confused... I agree, CONFIG_UTRACE_PTRACE should die. But what about !CONFIG_UTRACE case? What should we do with arches which doesn't use tracehooks or play with ptrace internals? > > But this patch was needed for child-data cleanups. However, I think we > > should forget about these cleanups for now. > > What?!? The whole point of tracee data structure cleanup was to fit it > cleanly with utrace. i.e., to have a thing to hang off engine->data. > I don't understand why you'd want to abandon that now. Firstly, these changes can't be applied until we fix arch/ which play with ->ptrace. Also. Currently I do not see how these cleanups can really help for the first working version of utrace-ptrace. For example, if we kill task->parent, we need more changes for the first version. Instead, I think it makes sense to do these cleanups on top of utrace-ptrace. Oleg. From roland at redhat.com Wed Aug 5 00:35:35 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 4 Aug 2009 17:35:35 -0700 (PDT) Subject: [PATCH 5/6] finish_utrace_stop: check ->stopped lockless In-Reply-To: Oleg Nesterov's message of Wednesday, 5 August 2009 01:24:18 +0200 <20090804232418.GA26768@redhat.com> References: <20090731010656.GA8074@redhat.com> <20090802002225.89D534C87C@magilla.sf.frob.com> <20090803143331.GA6050@redhat.com> <20090803190658.D643641063@magilla.sf.frob.com> <20090804232418.GA26768@redhat.com> Message-ID: <20090805003535.4975441063@magilla.sf.frob.com> > What I meant, we can rely on the fact that any wakeup (try_to_wakeup() > actually) must be a barrier wrt schedule(). Ok. > But what if the tracee is woken by CONT/KILL? Should the tracee > see the last change in ->stopped? The signal can race with > utrace_wakeup() or utrace_do_stop(), [...] It can't actually race with utrace_do_stop, because that holds siglock while touching ->stopped. Any signal case should already exclude utrace_do_stop that way. So it's only utrace_wakeup, which clears ->stopped before taking siglock--and that's the harmless direction to race. > But I think all we need is to be sure that: > > - if ->stopped == T, we have a pending SIGKILL > > If we were woken by SIGCONT which comes right after > utrace_wakeup() does s/TRACED/STOPPED/, I think we must > see the result of "->stopped = 0" in utrace_wakeup(). > Both utrace_wakeup() and signal_wake_up() take ->siglock, > the memory change in ->stopped must be visible to > utrace_wakeup() and the wakee. Ok. > - If we were killed, we must see ->stopped == T _unless_ > utrace_wakeup() is in progress or we are already woken > from utrace pov. Right. In those cases it doesn't matter whether we think we were killed or not. It can be "before" the wakeup or "after" the wakeup. > Now we should worry about SIGKILL racing with utrace_do_stop(). > Again, both take ->siglock, etc. > > But in short, I can't understand how utrace->lock can really help, > given that a signal changes task's state without this lock. It can > only help to avoid the races with utrace playing with ->stopped in > parallel, but I see nothing dangerous here. Right, I just meant about keeping ->stopped "correct" in the signal case. i.e., in case of signal wakeup, it could never see an old ->stopped value. > > Shouldn't one always hold siglock to use task->pending at all? > > Why? It only checks the bit. Note that fatal_signal_pending() is > used lockless. Ok. > But this discussion makes me wonder, what report->killed and > utrace_stop's returned value buy us? Can't we kill report->killed > and make utrace_stop() return void? I think at some point earlier I was not confident that a local pending SIGKILL would always be there. This was before we had fatal_signal_pending et al. It might not have been a valid worry even then. > With or without this patch. Suppose that (say) utrace_report_syscall_entry() > does utrace_stop() and sleeps in TASK_TRACED. Another thread starts the > group stop and sets SIGNAL_STOP_STOPPED. utrace_wakeup() clears ->stopped, > notices SIGNAL_STOP_STOPPED and doesn't wake up. > > Now, we can sleep a long time. Then SIGKILL kills us, but finish_utrace_stop() > returns false. Yes, that's a good point. > Afaics, only utrace_get_signal() uses report.kill, and only > utrace_report_syscall_entry() uses the result of utrace_stop(). Both > can just check fatal_signal_pending(). Ok. > > You mean the tracehook_notify_jctl(why, CLD_CONTINUED) case, right? > > Not sure. utrace_get_signal() can call ->report_signal() before it > takes utrace->lock. Right. It couldn't before af3eb44. > Heh. Actually, I was wrong. utrace_report_jctl() is not possible if the > tracee is killed. complete_signal(SIGKILL) sets ->flags = SIGNAL_GROUP_EXIT. Ah, good. > > OTOH we can just keep utrace_finish_jctl() and have it and > > finish_utrace_stop() just always take the utrace lock purely > > to synchronize (and then drop it without changing anything). > > or we can just do spin_unlock_wait(). I guess that has the same effect as lock+unlock, sure. > Anyway, I believe that this change, even if good, is low priority. I mean, > it doesn't immediately makes possible other improvements, afaics. But this > all is up to you. No, but it is up to you! ;-) The point of the exercise is to get utrace merged upstream. We will of course keep refining it in the future. My attention to the idea of dropping ->stopped now was purely on the thought that it might make the code easier to understand/review/believe correct so it could help with upstream reviewers liking it for merge. So do it if it helps or do the opposite if that helps, or play it by ear as feels right. Thanks, Roland From roland at redhat.com Wed Aug 5 01:09:11 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 4 Aug 2009 18:09:11 -0700 (PDT) Subject: utrace_ptrace && task->ptrace In-Reply-To: Oleg Nesterov's message of Wednesday, 5 August 2009 01:54:58 +0200 <20090804235458.GB26768@redhat.com> References: <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> <20090723190234.GA12037@redhat.com> <20090724230649.8FD1C80563@magilla.sf.frob.com> <20090803232253.GA5682@redhat.com> <20090804021123.581B241063@magilla.sf.frob.com> <20090804235458.GB26768@redhat.com> Message-ID: <20090805010911.2A69541063@magilla.sf.frob.com> > Actually the very first "for utrace-devel only" version should be just > your utrace-ptrace.patch + attach/detach fixes. Not that I can verify > this, but I hope that ptrace_utrace_ops's methods are more or less right. > (but of course, we should recheck them as much is possible). The utrace_ops parts of that code are probably not too far off, but the rest of it is really no starting place. Like I've said before, you should be starting from scratch and just yanking little bits out of that old patch that are useful. I'm sure some of the kludge factor will be reduced greatly by not trying to make it conditional. But the big wrongnesses are things like ptrace_set_action() et al. Not to mention the whole wakeup and synchronization regime, which is why we had that whole discussion earlier. (And it's not just not clean, it's known to be buggy! So it's not to be presumed a decent guide for anything.) > Than we can move some things into engine->data. Right now my only concern > is attach/detach, and the only method which needs the immediate attention > is ptrace_resumed() which (afaics wrongly) does the "deferred" detach. I'm open to whatever you like that gets the semantics right. I can't see how PTRACE_DETACH with nonzero argument (detach-parting-signal.c case in ptrace-tests) can be done anything remotely like cleanly unless you keep the utrace_engine around to have a final report_signal callback. > I agree, CONFIG_UTRACE_PTRACE should die. But what about !CONFIG_UTRACE > case? What should we do with arches which doesn't use tracehooks or > play with ptrace internals? AIUI hch wants to have ptrace rely on utrace. Those either get no ptrace (we cond_syscall it) and/or just stop building if not updated. Maybe he can give you some more direct advice about what the merging plan should be. The tracehook conversion is pretty simple for every arch, even for non-arch people (if you just punt the syscall-abort support, which is a new feature and so a non-regressing incremental step). > Firstly, these changes can't be applied until we fix arch/ which play > with ->ptrace. Only a few arch's overload ->ptrace for private purposes, and I don't foresee any problem getting those fixed up soon. (The parisc maintainer is doing it already. I think xtensa might have something on deck. I can do the arm changes if anybody will ever review and merge them.) > Also. Currently I do not see how these cleanups can really help for the > first working version of utrace-ptrace. For example, if we kill task->parent, > we need more changes for the first version. Your ptrace code will need to record some state somewhere, beyond the legacy ptrace fields. ptrace_ctx hung off engine->data is the natural place for all that state. That's why I figured we'd want some of those cleanups (at least having the struct at all) before doing utrace-ptrace. In short, I think when you get satisfactorily working ptrace code going you will have had to do enough new stuff that cleanup beforehand seems preferable. But it's up to you. Get it merged ASAP, get it clean eventually. Sometimes getting it clean first helps get it merged, but maybe not. Always getting it working well and readably so helps getting it merged, and sometimes getting it clean helps with those. Thanks, Roland From newsletter at usbportugal.com Wed Aug 5 01:35:20 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Wed, 5 Aug 2009 03:35:20 +0200 Subject: =?iso-8859-1?q?J=E1_n=E3o_h=E1_mem=F3ria_de=2E=2E=2ESemana_32?= Message-ID: <4f7ef27b5fa950f91e458ce3e6b7355d@newsletter1.usbportugal.com> An HTML attachment was scrubbed... URL: From hch at lst.de Wed Aug 5 15:13:09 2009 From: hch at lst.de (Christoph Hellwig) Date: Wed, 5 Aug 2009 17:13:09 +0200 Subject: utrace_ptrace && task->ptrace In-Reply-To: <20090805010911.2A69541063@magilla.sf.frob.com> References: <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> <20090723190234.GA12037@redhat.com> <20090724230649.8FD1C80563@magilla.sf.frob.com> <20090803232253.GA5682@redhat.com> <20090804021123.581B241063@magilla.sf.frob.com> <20090804235458.GB26768@redhat.com> <20090805010911.2A69541063@magilla.sf.frob.com> Message-ID: <20090805151309.GD5535@lst.de> On Tue, Aug 04, 2009 at 06:09:11PM -0700, Roland McGrath wrote: > > I agree, CONFIG_UTRACE_PTRACE should die. But what about !CONFIG_UTRACE > > case? What should we do with arches which doesn't use tracehooks or > > play with ptrace internals? > > AIUI hch wants to have ptrace rely on utrace. Those either get no ptrace > (we cond_syscall it) and/or just stop building if not updated. Maybe he > can give you some more direct advice about what the merging plan should be. > > The tracehook conversion is pretty simple for every arch, even for non-arch > people (if you just punt the syscall-abort support, which is a new feature > and so a non-regressing incremental step). Really architectures should be converted, and it would help if someone else could ping the outstanding architectures again. At some point if they are few enough we can just break them. > > Firstly, these changes can't be applied until we fix arch/ which play > > with ->ptrace. > > Only a few arch's overload ->ptrace for private purposes, and I don't > foresee any problem getting those fixed up soon. (The parisc maintainer is > doing it already. I think xtensa might have something on deck. I can do > the arm changes if anybody will ever review and merge them.) Converting the architectures to tracehooks and new-style ptrace should mostly take care of it like for parisc. As for arm you might have to push it a bit more, it didn't seem like rmk was very excited about your first set of patches. From oleg at redhat.com Thu Aug 6 00:57:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 6 Aug 2009 02:57:35 +0200 Subject: Q: ptrace_detach() && UTRACE_DETACH Message-ID: <20090806005735.GA21003@redhat.com> Still no code, only questions. One particular problem with attach/detach is that ptrace_detach_task(sig) doesn't really detach if sig != 0. Instead of UTRACE_DETACH we clear engine->data and do UTRACE_INTERRUPT. The actual detach should be done by ptrace_report_signal()->ptrace_resumed which returns UTRACE_DETACH if engine->data == NULL. If another ptracer comes in between, it reuses this engine and sets the new value of ->data. This creates a lot of problems, and I can't find any solution. And I feel we will have more problems when we move more data into engine->data. Questions: 1. Suddenly I realized, I do not really understand why ptrace_attach() tries to reuse the "almost detached" engine. Can't attach just fail in this case as if the task is still ptraced? ptrace_detach() always wakes up the tracee. This means it should call utrace_get_signal() soon and complete the detach. Yes, ptrace_detach()->wake_up_process() is actually wrong. This is not friendly if the tracee has other tracers. In fact it is wrong in any case if we want to respect SIGNAL_STOP_STOPPED like utrace_wakeup() does, but this was already discussed. But, until we change/fix this unconditinal wakeup, any other reason why the new debugger should try to re-use? 2. Or. Perhaps we can add ptrace_utrace_detached_ops ? All methods should return UTRACE_DETACH, except ptrace_utrace_detached_ops->report_signal() fixups ->last_siginfo and returns UTRACE_SIGNAL_XXX | UTRACE_DETACH. ptrace_detach_task() sets engine->ops = ptrace_utrace_detached_ops before utrace_control(UTRACE_INTERRUPT). We don't even need utrace_barrier(). This means that the new debugger can another engine. Do you think this can work? 3. A bit off-topic question. I can't understand ptrace_detach(sig) with ptrace_report_syscall(). Currently (without utrace), if we detach when the tracee sleeps after ptrace_report_syscall()->ptrace_notify(), we set ->exit_code = sig and the tracee send this sig to itself after wakeup. But, utrace-ptrace does this differently. report_syscall_xxx() do not play with signals, instead when ptracer does PTRACE_CONT/etc we send the signal to tracee before wakeup. (btw, send_sig() is wrong, the child can be dead without ->signal). This means that with utrace-ptrace ptrace_detach(sig) does not imply the signal if the tracee reported PTRACE_EVENT_SYSCALL. Should be fixed or I missed something? Oleg. From srikar at linux.vnet.ibm.com Thu Aug 6 11:02:16 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Thu, 6 Aug 2009 16:32:16 +0530 Subject: [PATCH] gdbstub/uprobes : uprobe_unregister with halted target In-Reply-To: <20090804142305.GB27203@linux.vnet.ibm.com> References: <20090731194622.GC12318@redhat.com> <20090731220849.GD12318@redhat.com> <1249085124.5082.83.camel@localhost.localdomain> <20090803064927.GD27318@linux.vnet.ibm.com> <1249323000.5397.19.camel@localhost.localdomain> <20090804142305.GB27203@linux.vnet.ibm.com> Message-ID: <20090806110216.GA15755@linux.vnet.ibm.com> Hi, This is a patch to gdbstub that provides a "workaround" for the problem reported by Frank " gdbstub/uprobes problems: uprobe_unregister with halted target" I also want to know if it's possible to have soft breakpoints (or traps) handled by gdb in multiple ways, i.e one from stub (using uprobes), the other from gdb itself(example handle)? I call this a workaround because this patch expects all SIGTRAPS to be handled by stub and need not be sent to gdb for processing. i.e (gdb) handle SIGTRAP may not work. However I dont think its wrong assumption to make because when gdb inserts a breakpoint when using a remote protocol and gdb stub uses uprobes then its better left to uprobes. In this case, when gdbstub hits a breakpoint, it should either be handled by uprobes or passed to the program. Please do let me know if this is a wrong assumption. -- Signed-Off-by: Srikar Dronamraju diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index edf2769..a11fa9a 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -341,6 +341,7 @@ u32 gdb_utrace_report_signal(u32 action, struct gdb_connection *p = engine->data; u32 ret = action; int kern_p; + unsigned int signo = map_signal_kern2gdb(info->si_signo); mutex_lock(&p->output_mutex); @@ -354,7 +355,9 @@ u32 gdb_utrace_report_signal(u32 action, * * 1) This is an ordinary signal. We UTRACE_STOP to notify gdb. * - * 2) This is a SIGTRAP arising from a breakpoint. We UTRACE_STOP. + * 2) This is a SIGTRAP arising from a breakpoint. + * If we have uprobes support: allow uprobes to handle it: UTRACE_RESUME. + * Else UTRACE_STOP. * * 3) This is a signal our code injected to stop the process, in lieu * of UTRACE_INTERRUPT. We UTRACE_STOP | UTRACE_SIGNAL_IGN. @@ -377,12 +380,18 @@ u32 gdb_utrace_report_signal(u32 action, ret = UTRACE_RESUME; /* deliver */ } else if (p->stop_signals > 0 /*&& kern_p*/) { /* Case 3 */ p->stop_signals --; - snprintf (p->stopcode, GDB_BUFMAX, "S%02x", map_signal_kern2gdb(info->si_signo)); + snprintf (p->stopcode, GDB_BUFMAX, "S%02x", signo); push_output_packet (p, p->stopcode); p->at_quiesce_do = UTRACE_STOP; ret = UTRACE_STOP | UTRACE_SIGNAL_IGN; - } else { /* Cases 1, 2 */ - snprintf (p->stopcode, GDB_BUFMAX, "S%02x", map_signal_kern2gdb(info->si_signo)); +#ifdef CONFIG_HAVE_UPROBES + } else if (info->si_signo == signo) { + p->skip_signals --; + p->at_quiesce_do = UTRACE_RESUME; + ret = UTRACE_RESUME; /* deliver */ +#endif /* CONFIG_HAVE_UPROBES */ + } else { /* Cases 1, 2 */ + snprintf (p->stopcode, GDB_BUFMAX, "S%02x", signo); push_output_packet (p, p->stopcode); p->at_quiesce_do = UTRACE_STOP; ret = UTRACE_STOP; From newsletter at brinde-companhia.com Thu Aug 6 23:41:17 2009 From: newsletter at brinde-companhia.com (Brinde & Companhia) Date: Fri, 7 Aug 2009 01:41:17 +0200 Subject: =?iso-8859-1?q?O_Agosto_n=E3o_para=2E=2E=2E?= Message-ID: An HTML attachment was scrubbed... URL: From info at canal-direct.com Fri Aug 7 14:10:00 2009 From: info at canal-direct.com (=?ISO-8859-1?Q?Decision_MD?=) Date: Fri, 07 Aug 2009 16:10:00 +0200 Subject: Des solutions pour des campagnes E-mail efficaces Message-ID: An HTML attachment was scrubbed... URL: From roland at redhat.com Fri Aug 7 19:45:41 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 7 Aug 2009 12:45:41 -0700 (PDT) Subject: Q: ptrace_detach() && UTRACE_DETACH In-Reply-To: Oleg Nesterov's message of Thursday, 6 August 2009 02:57:35 +0200 <20090806005735.GA21003@redhat.com> References: <20090806005735.GA21003@redhat.com> Message-ID: <20090807194541.1D3DF4213B@magilla.sf.frob.com> > 1. Suddenly I realized, I do not really understand why ptrace_attach() > tries to reuse the "almost detached" engine. Can't attach just fail > in this case as if the task is still ptraced? No (unless it's actually a race with the first PTRACE_DETACH call). Consider: ptrace(PTRACE_DETACH, pid, 0, SIGUSR1); ptrace(PTRACE_ATTACH, pid); Assume the tracee doesn't get scheduled in between those two calls. The caller synchronously knows (given error checking omitted above) that the tracee is no longer traced after PTRACE_DETACH, so calling PTRACE_ATTACH again is correct and raceless. However, the behavior requirement is that the tracee deliver (not queue) the SIGUSR1 before the tracer can see it do anything else after the second attach. (BTW, however the new code you write comes out, please make sure it is full of comments that explain these sorts of subtleties that constrain the design.) > ptrace_detach() always wakes up the tracee. This means it should call > utrace_get_signal() soon and complete the detach. Right. But "soon" is not a guaranteed ordering. > But, until we change/fix this unconditinal wakeup, any other reason why > the new debugger should try to re-use? I don't think it matters specifically that it reuse the old engine. That's an implementation detail you can change. What matters is that the parting signal gets delivered. The "almost detached" engine is the way that happens. Its final report_signal callback needs to run before the new engine first processes any signal. The new engine should have no way to intercept the parting signal. i.e., it happens before the first possible ptrace stop (of the second attach). If you were to attach the new engine along with the lingering old engine, then it would get a report_signal callback as if the parting signal were a newly-dequeued signal. So you have to avoid that somehow. > 2. Or. Perhaps we can add ptrace_utrace_detached_ops ? All methods should > return UTRACE_DETACH, except ptrace_utrace_detached_ops->report_signal() > fixups ->last_siginfo and returns UTRACE_SIGNAL_XXX | UTRACE_DETACH. I'm not entirely positive there aren't any cases where another callback would be made before the report_signal. I think the only one where a plain UTRACE_DETACH would be correct is report_death (for SIGKILL). Otherwise, a UTRACE_DETACH that abandons the parting signal is wrong. There may well be none, since it has to be in a ptrace-reported stop already before PTRACE_DETACH works. But it needs more thought. > ptrace_detach_task() sets engine->ops = ptrace_utrace_detached_ops before > utrace_control(UTRACE_INTERRUPT). We don't even need utrace_barrier(). > > This means that the new debugger can another engine. > > Do you think this can work? Perhaps. In the utrace API it is not really kosher ever to change the ->ops pointer. But this just means we would have to carefully examine the utrace code paths and say what the true rules are about when and how changing ->ops is safe. > 3. A bit off-topic question. I can't understand ptrace_detach(sig) with > ptrace_report_syscall(). > > Currently (without utrace), if we detach when the tracee sleeps after > ptrace_report_syscall()->ptrace_notify(), we set ->exit_code = sig and > the tracee send this sig to itself after wakeup. Right. > But, utrace-ptrace does this differently. report_syscall_xxx() do not > play with signals, instead when ptracer does PTRACE_CONT/etc we send > the signal to tracee before wakeup. report_syscall_* run before the stop. What signal (if any) to send is not chosen until the wakeup (obviously, since it's an argument to the waking ptrace call). In the case of syscall entry, there isn't any place in the tracee where we have a hook that runs after wakeup and before the actual syscall. If we were to merge the utrace-syscall-resumed branch API change, then it would be possible to use the after-resume second report_syscall_entry to do it. We probably do want that API change or something like it anyway (see the previous discussion about that, which petered out). But off hand I don't see any particular reason it matters which of these two places this send_sig() call goes. > (btw, send_sig() is wrong, the child can be dead without ->signal). ... except for this. ;-) > This means that with utrace-ptrace ptrace_detach(sig) does not imply > the signal if the tracee reported PTRACE_EVENT_SYSCALL. > > Should be fixed or I missed something? One of us is missing something, because I didn't expect that result. Since it's even in question, I think we should clearly have a case in the ptrace-tests suite that specifically tests this behavior. I haven't looked closely at the old utrace-ptrace.patch code in a while. (I keep telling you, you're not fixing this old code, you're writing it correctly yourself!) Indeed, that looks wrong, that this special-case logic for PTRACE_EVENT_SYSCALL is not done for the PTRACE_DETACH case. This does seem notably cleaner with the utrace-syscall-resumed API. Then the send_sig() special case is only in the report_syscall_* callbacks in particular (using the resumed case of the entry hook) and not on the wakeup side. If PTRACE_DETACH keeps the current plan for parting signals (as I think it must), then these callbacks will naturally dtrt by treating resumed-with-signal the same whether it's a normal resumption or an "almost detached" final callback. Thanks, Roland From pdelaney at tensilica.com Fri Aug 7 21:19:10 2009 From: pdelaney at tensilica.com (Piet Delaney) Date: Fri, 7 Aug 2009 14:19:10 -0700 Subject: utrace_ptrace && task->ptrace In-Reply-To: <20090805010911.2A69541063@magilla.sf.frob.com> References: <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> <20090723190234.GA12037@redhat.com> <20090724230649.8FD1C80563@magilla.sf.frob.com> <20090803232253.GA5682@redhat.com> <20090804021123.581B241063@magilla.sf.frob.com> <20090804235458.GB26768@redhat.com> <20090805010911.2A69541063@magilla.sf.frob.com> Message-ID: <4A7C9A4E.1010201@tensilica.com> Roland McGrath wrote: > Only a few arch's overload ->ptrace for private purposes, and I don't > foresee any problem getting those fixed up soon. (The parisc maintainer is > doing it already. I think xtensa might have something on deck. I can do > the arm changes if anybody will ever review and merge them.) I thought I check on xtensa having something on deck. I'd like to test it if possible to avoid surprises and if it's not ready, and needs to be, then to include this while submitting SMP changes in the not too distant future. -piet From roland at redhat.com Fri Aug 7 21:26:04 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 7 Aug 2009 14:26:04 -0700 (PDT) Subject: utrace_ptrace && task->ptrace In-Reply-To: Piet Delaney's message of Friday, 7 August 2009 14:19:10 -0700 <4A7C9A4E.1010201@tensilica.com> References: <20090716233517.BA7A44702D@magilla.sf.frob.com> <20090720152652.GA17395@redhat.com> <20090721231502.849956D036@magilla.sf.frob.com> <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> <20090723190234.GA12037@redhat.com> <20090724230649.8FD1C80563@magilla.sf.frob.com> <20090803232253.GA5682@redhat.com> <20090804021123.581B241063@magilla.sf.frob.com> <20090804235458.GB26768@redhat.com> <20090805010911.2A69541063@magilla.sf.frob.com> <4A7C9A4E.1010201@tensilica.com> Message-ID: <20090807212604.111BB4213B@magilla.sf.frob.com> > I thought I check on xtensa having something on deck. > I'd like to test it if possible to avoid surprises and > if it's not ready, and needs to be, then to include this > while submitting SMP changes in the not too distant future. Sorry, that was a dim recollection of mine and it appears to have been entirely mistaken. I don't know anything about xtensa. Thanks, Roland From alexandre at unimedplanosdesaude.com.br Sat Aug 8 03:43:36 2009 From: alexandre at unimedplanosdesaude.com.br (Alexandre Unimed/Seven) Date: Sat, 8 Aug 2009 03:43:36 GMT Subject: =?iso-8859-1?q?Novas_Informa=E7=F5es_Unimed?= Message-ID: O Que Te Leva a Escolher um Plano de Saude? Plano de saude tem de ter qualidade e pre?o baixo, e ? por isso que a UNIMED ? a sua escolha. Com planos a partir de R$ 69.94*. Com atendimento nos melhores Hopitais** como:Hospital Alem?o Oswaldo Cruz, Hospital S?rio Liban?s, Pronto Socorro Infantil Sabar?, Hospital S?o Luis , Hospital Nove de Julho, Pr?-Matre Paulista e muito mais, na Unimed voc? e sua familia ter?o o melhor atendimento e a maior rede pr?pria do pais. Corra para a Unimed, e aproveite todas as nossas vantagens! Clientes Unimed contam com mais de 106 mil m?dicos**, 3.244 hospitais credenciados**, al?m de pronto-atendimentos, laborat?rios, ambul?ncias e hospitais pr?prios e credenciados para garantir qualidade na assist?ncia m?dica, hospitalar e de diagn?stico complementar oferecidos. Planos Nacionais***, Descontos em farmacias****. Acesse agora nosso site e solicite uma cota??o voc? ter? o melhor atendimento, nossa equipe ir? te ajudar a escolher um plano que realmente supere suas epectativas. Ligue agora (11) 3467-9557 estamos esperando por voc? . Seja um plano para voc?,sua familia ou para sua empresa. Na Unimed voc? encontra plano empresarial com redu??o de at? 30% nos valores apartir de 2 vidas. Acesse agora www.unimedplanosdesaude.com.br Em nosso site voc? encontra informa??es como:portabilidade, novos procedimentos obrigat?rios nos plano de saude e muito mais. Ou Ligue (11) 3467-9557 *valor referente faixa etaria de 0 a 18 anos ja com desconto promocional soliticite maiores informa??es com nossos consultores. **Dependendo do plano escolhido . ***Atendimento Nacional dependendo do plano escolhido para urgencia e emergencia. ****Solicite informa??o sobre farmacias participantes. OBS: Caso voc? n?o deseje mais receber nenhum tipo de contato nosso, clique aqui , ou envie um e-mail para remover at unimedplanosdesaude.com.br com o assunto REMOVER. www.samcilassistenciamedica.com.br -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: topo_unimed.gif Type: image/gif Size: 155282 bytes Desc: not available URL: From hch at lst.de Sat Aug 8 21:41:22 2009 From: hch at lst.de (Christoph Hellwig) Date: Sat, 8 Aug 2009 23:41:22 +0200 Subject: utrace_ptrace && task->ptrace In-Reply-To: <4A7C9A4E.1010201@tensilica.com> References: <20090722182517.GC7305@redhat.com> <20090722182941.GD7305@redhat.com> <20090723012325.903F62D36@magilla.sf.frob.com> <20090723190234.GA12037@redhat.com> <20090724230649.8FD1C80563@magilla.sf.frob.com> <20090803232253.GA5682@redhat.com> <20090804021123.581B241063@magilla.sf.frob.com> <20090804235458.GB26768@redhat.com> <20090805010911.2A69541063@magilla.sf.frob.com> <4A7C9A4E.1010201@tensilica.com> Message-ID: <20090808214122.GA25141@lst.de> On Fri, Aug 07, 2009 at 02:19:10PM -0700, Piet Delaney wrote: > Roland McGrath wrote: > > >Only a few arch's overload ->ptrace for private purposes, and I don't > >foresee any problem getting those fixed up soon. (The parisc maintainer is > >doing it already. I think xtensa might have something on deck. I can do > >the arm changes if anybody will ever review and merge them.) > > I thought I check on xtensa having something on deck. > I'd like to test it if possible to avoid surprises and > if it's not ready, and needs to be, then to include this > while submitting SMP changes in the not too distant future. While not directly related to that issue it would be good if you could take a look at http://sourceware.org/systemtap/wiki/utrace/arch/HowTo and convert xtensa to new-style ptrace code described there. That should also make your future maintaince easier by requiring less and better structured architecture code. From oleg at redhat.com Mon Aug 10 14:03:55 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 10 Aug 2009 16:03:55 +0200 Subject: Q: ptrace_detach() && UTRACE_DETACH In-Reply-To: <20090807194541.1D3DF4213B@magilla.sf.frob.com> References: <20090806005735.GA21003@redhat.com> <20090807194541.1D3DF4213B@magilla.sf.frob.com> Message-ID: <20090810140355.GA7816@redhat.com> On 08/07, Roland McGrath wrote: > > > 1. Suddenly I realized, I do not really understand why ptrace_attach() > > tries to reuse the "almost detached" engine. Can't attach just fail > > in this case as if the task is still ptraced? > > No (unless it's actually a race with the first PTRACE_DETACH call). > Consider: > > ptrace(PTRACE_DETACH, pid, 0, SIGUSR1); > ptrace(PTRACE_ATTACH, pid); Indeed, you are right. The caller of DETACH has all rights to assume ATTACH must succeed. I missed this. > However, the behavior requirement is that the tracee deliver (not queue) > the SIGUSR1 before the tracer can see it do anything else after the second > attach. > ... > The new engine should have no way to intercept the parting signal. > i.e., it happens before the first possible ptrace stop (of the second > attach). If you were to attach the new engine along with the lingering > old engine, then it would get a report_signal callback as if the parting > signal were a newly-dequeued signal. So you have to avoid that somehow. Hmm. Another problem I didn't think of... > > 2. Or. Perhaps we can add ptrace_utrace_detached_ops ? All methods should > > return UTRACE_DETACH, except ptrace_utrace_detached_ops->report_signal() > > fixups ->last_siginfo and returns UTRACE_SIGNAL_XXX | UTRACE_DETACH. > > I'm not entirely positive there aren't any cases where another callback > would be made before the report_signal. Yes. But, afaics, if another callback can be called before report_signal then we don't have a valid ->last_siginfo. IOW. ptrace_detach(signr) should have effect only if the tracee sleeps in utrace_get_signal()->finish_resume_report() path, right ? (I am ignoring report_syscall case for now). This means, before utrace_get_signal() is called with ->interrupt == T, the only possible callback is utrace_report_jctl()->ptrace_report_quiesce(). > > ptrace_detach_task() sets engine->ops = ptrace_utrace_detached_ops before > > utrace_control(UTRACE_INTERRUPT). We don't even need utrace_barrier(). > > > > This means that the new debugger can another engine. > > > > Do you think this can work? > > Perhaps. In the utrace API it is not really kosher ever to change the > ->ops pointer. But this just means we would have to carefully examine > the utrace code paths and say what the true rules are about when and how > changing ->ops is safe. I think this should be safe. The tracee should be stopped. We can only race with SIGKILL, but given that old ->ops = ptrace_utrace_ops can't go away I think nothing bad can happen. Or we can do spin_lock(utrace->lock); if (utrace->stopped) engine->ops = new_ops; /* else: it is killed, we don't care */ spin_unlock(utrace_lock); Anyway. I am not proud of this idea, and it needs more thinking in any case. Or. Perhaps. detach can just mark engine as detached, and ptrace_attach() does utrace_attach_task() without UTRACE_ATTACH_EXCLUSIVE. This means we should rely on PT_PTRACED, not good. And this means we should teach ptrace_utrace_ops's methods to take this case into account. I don't think this is good idea... > > But, utrace-ptrace does this differently. report_syscall_xxx() do not > > play with signals, instead when ptracer does PTRACE_CONT/etc we send > > the signal to tracee before wakeup. > > But off hand I don't see any particular reason it matters which of these > two places this send_sig() call goes. Yes, ptrace_resume(PTRACE_EVENT_SYSCALL)->send_sig() looks good to me. Except, > > This means that with utrace-ptrace ptrace_detach(sig) does not imply > > the signal if the tracee reported PTRACE_EVENT_SYSCALL. > > > > Should be fixed or I missed something? > > One of us is missing something, because I didn't expect that result. > Since it's even in question, I think we should clearly have a case in > the ptrace-tests suite that specifically tests this behavior. OK, so this should be fixed somehow... > I haven't looked closely at the old utrace-ptrace.patch code in a while. > (I keep telling you, you're not fixing this old code, you're writing it > correctly yourself!) Roland, if only I knew how to improve the old utrace-ptrace.patch! If only I knew how to write it correctly from scratch... And giwen that it must be ready asap, my only hope is to make some fixes against this old utrace-ptrace.patch. And I still have no idea how to solve the problems with detach. Well, perhaps swithing engine->ops can work... Other problems with attach/detach which are more or less simple: 1. ptrace_check_attach() must check child->parent == current. We can do this without tasklist. 2. ptrace_attach() should do prepare_ptrace_attach() after security checks, under ->cred_guard_mutex. 3. ptrace_traceme() does prepare_ptrace_attach() before security checks too... Not good, this can deny ptrace_attach() from another tracer, but hopefully we can ignore this problem for now. 4. ptrace_utrace_exit() is called from tracehook_report_exit(). This is not right, we can race with ptrace_traceme(). We should move this code into exit_ptrace() which is called when we already have PF_EXITING. 5. ptrace_report_clone() is racy. parent->parent can exit and untrace child before utrace_attach_task(child, UTRACE_ATTACH_CREATE ...). This _looks_ fixeable, we should check child->ptrace after utrace_attach_task(), if the tracee is no longer traced we can do utrace_control(UTRACE_DETACH). The child is not stopped from utrace's pov, but at least we know utrace_get_signal() should complete the detach later. (CLONE_PTRACE is not right too, but this is minor). Anything else I missed? But again. I still have no idea how to fix the problems with ptrace_detach(signr) which doesn't do UTRACE_DETACH. I am stuck. Oleg. From fche at redhat.com Mon Aug 10 16:42:10 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Mon, 10 Aug 2009 12:42:10 -0400 Subject: gdbstub/uprobes problems: uprobe_unregister with halted target In-Reply-To: <1249323000.5397.19.camel@localhost.localdomain> References: <20090731194622.GC12318@redhat.com> <20090731220849.GD12318@redhat.com> <1249085124.5082.83.camel@localhost.localdomain> <20090803064927.GD27318@linux.vnet.ibm.com> <1249323000.5397.19.camel@localhost.localdomain> Message-ID: <20090810164210.GH2926@redhat.com> Hi - On Mon, Aug 03, 2009 at 11:10:00AM -0700, Jim Keniston wrote: > [...] > > So as per my analysis, gdb_utrace_report_signal was called, followed by > > uprobe_report_signal. Since gdb_utrace_report_signal requested for > > UTRACE_STOP as resume action for SIGTRAP, the thread got stopped. > > [...] A variant of this problem still exists, despite switching to a deferred uprobes-unregister operation (now done at gdb-disconnect time), but even then sometimes the process is stopped mid-singlestep. It seems to me that a more robust solution for registering/unregistering these probes is necessary - one that tolerates the threads being in stopped or running or whatever state. Another problem: under some conditions, it seems we can have a race between uprobes and gdbstub w.r.t. the handling of the SSOL instructions. Sometimes by the time the gdbstub's uprobe-handler code is called, and some time later, gdb starts asking for register contents, the user-regset PC has been updated to point at the SSOL memory page. GDB can't make heads or tails of that. I don't know if this is a symptom of a deeper utrace issue. I pushed my current version of utrace-gdbstub-uprobes for your joint pain-sharing. - FChE From jkenisto at us.ibm.com Mon Aug 10 23:52:08 2009 From: jkenisto at us.ibm.com (Jim Keniston) Date: Mon, 10 Aug 2009 16:52:08 -0700 Subject: gdbstub/uprobes problems: uprobe_unregister with halted target In-Reply-To: <20090810164210.GH2926@redhat.com> References: <20090731194622.GC12318@redhat.com> <20090731220849.GD12318@redhat.com> <1249085124.5082.83.camel@localhost.localdomain> <20090803064927.GD27318@linux.vnet.ibm.com> <1249323000.5397.19.camel@localhost.localdomain> <20090810164210.GH2926@redhat.com> Message-ID: <1249948328.5141.64.camel@localhost.localdomain> On Mon, 2009-08-10 at 12:42 -0400, Frank Ch. Eigler wrote: > Hi - > > On Mon, Aug 03, 2009 at 11:10:00AM -0700, Jim Keniston wrote: > > [...] > > > So as per my analysis, gdb_utrace_report_signal was called, followed by > > > uprobe_report_signal. Since gdb_utrace_report_signal requested for > > > UTRACE_STOP as resume action for SIGTRAP, the thread got stopped. > > > [...] > > A variant of this problem still exists, despite switching to a > deferred uprobes-unregister operation (now done at gdb-disconnect > time), but even then sometimes the process is stopped mid-singlestep. > It seems to me that a more robust solution for > registering/unregistering these probes is necessary - one that > tolerates the threads being in stopped or running or whatever state. Srikar and I discussed this some. He may have some new ideas to try. Here's one idea that we didn't discuss. (Srikar may be the only one who can follow this....) Until recently, uprobes couldn't remove a probepoint while any probepoint hits were being processed. uproc->rwsem was read-locked basically from the time uprobe_report_signal() was called due to the breakpoint trap until after it had fixed up the IP and/or stack after the single-step trap -- hence PR #9828. So the first thing uprobe_report_quiesce() does is check to see if we're in the middle of single-stepping, and re-assert UTRACE_SINGLESTEP (and skip any other quiesce-time work) if so. At the end of uprobe-report_signal(), the call to utask_fake_quisece() handles any delayed quiesce-time work. But Srikar fixed up uprobes to drop uproc->rwsem while single-stepping, and handle the case where the active probepoint gets unregistered at that point. See, e.g., adjust_ip_active_ppt(). So it seems to me that uprobe_report_quiesce() should check utask->quiescing before checking (utask->state == UPTASK_SSTEP). If utask->quiescing is set, go ahead and do the quiesce-time work... If utask->active_probe gets deleted by the quiesce-time work, then you may have to do some cleanup associated with that probepoint hit that you'd normally do after single-stepping (uprobe_run_def_regs(), uprobe_inject_delayed_signals()). On the other hand, if utask->active_probe is still around after the quiesce-time work, then go ahead an assert UTRACE_SINGLESTEP as before. All this depends on uprobe_report_quiesce() actually getting called as a result of gdbstub's report_signal callback asserting UTRACE_STOP. Does it? Also, is uprobe_delay_signal() getting called much during these hangs? See PR #9826. > > Another problem: under some conditions, it seems we can have a race > between uprobes and gdbstub w.r.t. the handling of the SSOL > instructions. Sometimes by the time the gdbstub's uprobe-handler code > is called, and some time later, gdb starts asking for register > contents, the user-regset PC has been updated to point at the SSOL > memory page. GDB can't make heads or tails of that. I don't know if > this is a symptom of a deeper utrace issue. Uprobes knows which breakpoints it inserted. It refuses to register a probepoint where there's already a non-uprobes breakpoint, and it ignores breakpoint traps that aren't at uprobes probepoints. Can gdb/gdbstub be trained not to try to single-step at uprobes probepoints? If they don't keep track of their breakpoints, perhaps thay could ask uprobes: uprobes could export a wrapper for uprobe_find_probepoint() to answer this question. > > I pushed my current version of utrace-gdbstub-uprobes for your joint > pain-sharing. > > - FChE Jim From roland at redhat.com Tue Aug 11 01:25:21 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 10 Aug 2009 18:25:21 -0700 (PDT) Subject: Q: ptrace_detach() && UTRACE_DETACH In-Reply-To: Oleg Nesterov's message of Monday, 10 August 2009 16:03:55 +0200 <20090810140355.GA7816@redhat.com> References: <20090806005735.GA21003@redhat.com> <20090807194541.1D3DF4213B@magilla.sf.frob.com> <20090810140355.GA7816@redhat.com> Message-ID: <20090811012521.6F8DD4259E@magilla.sf.frob.com> > > I'm not entirely positive there aren't any cases where another callback > > would be made before the report_signal. > > Yes. But, afaics, if another callback can be called before report_signal > then we don't have a valid ->last_siginfo. I agree it sounds like a nice thing to be entirely positive about. But then some of the failure modes of the buggy old patch have to do with last_siginfo being wrong in ways I didn't understand, IIRC. > IOW. ptrace_detach(signr) should have effect only if the tracee sleeps > in utrace_get_signal()->finish_resume_report() path, right ? (I am ignoring > report_syscall case for now). syscall is the only contrary case that comes to mind. But indeed I think we can ignore it because the syscall case has its own special and different semantics (i.e. queuing) that we want to handle differently, as we discussed earlier. > This means, before utrace_get_signal() is called with ->interrupt == T, > the only possible callback is utrace_report_jctl()->ptrace_report_quiesce(). All sounds right to me. I'm just not confident I haven't missed something. That's what we have you for! ;-) > I think this should be safe. The tracee should be stopped. We can only > race with SIGKILL, but given that old ->ops = ptrace_utrace_ops can't go > away I think nothing bad can happen. Or we can do > > spin_lock(utrace->lock); > if (utrace->stopped) > engine->ops = new_ops; > /* else: it is killed, we don't care */ > spin_unlock(utrace_lock); > > Anyway. I am not proud of this idea, and it needs more thinking in any case. I don't doubt that we can find a set of rules by which it can work. But IMHO it's far better to keep it a very simple API rule that ->data belongs entirely to the engine but no other field should be touched directly. Of course, ptrace can always be a behind-the-curtain exception. But whenever we can avoid that, we will. > Or. Perhaps. detach can just mark engine as detached, and ptrace_attach() > does utrace_attach_task() without UTRACE_ATTACH_EXCLUSIVE. This means > we should rely on PT_PTRACED, not good. And this means we should teach > ptrace_utrace_ops's methods to take this case into account. I don't think > this is good idea... Here's another idea. Don't ever leave the regular ptrace_ops engine attached after PTRACE_DETACH. Instead, add another engine with a separate ops vector and event mask, just for the parting signal case. That engine is very simple: it only has to set UTRACE_EVENT(QUIESCE) implement the callbacks to inject the parting signal (and handle the corner cases). This way, the UTRACE_ATTACH_MATCH_OPS|UTRACE_ATTACH_EXCLUSIVE &ptrace_ops can still act as the arbiter of who is ptracing. (Though IIRC we still had an issue there with the order of the permission checks, but leave that aside for the moment.) When a new PTRACE_ATTACH comes along, it can get the new &ptrace_ops engine in place first. Then, knowing it's the sole tracer, it can also look up the lingering parting-signal engine with MATCH_OPS and notice the situation. I haven't thought through all the details. But this seems like a promising direction to me. > Roland, if only I knew how to improve the old utrace-ptrace.patch! > If only I knew how to write it correctly from scratch... Well, this is why we spent time understanding all the data structures controlling ptrace and cleaning them up. You now know more than anyone else about exactly what ptrace keeps track of and what requirements the moving parts have on each other wrt synchronization and the like. > And giwen that it must be ready asap, my only hope is to make some fixes > against this old utrace-ptrace.patch. And I still have no idea how to > solve the problems with detach. Well, perhaps swithing engine->ops can > work... We want it to be merged upstream ASAP. What will make that possible will be when it is clean enough, readable enough, behaves correctly, is rock-solid in the known torture tests, and is otherwise non-regressing, to the satisfaction of the upstream reviewers. If it's not ready by that definition, then there is no "ready" that matters, no matter how soon. Of course, always the sooner the better, and for all the aforementioned axes of perfection, incremental stumbling progress toward them is better than no running code. But AFAICT there is no benefit in any kind of rush job that doesn't take the time to get the innards right enough to pass muster upstream. > Other problems with attach/detach which are more or less simple: It sounds like you have fixes in mind. Just do them. Or just note them for later and leave these corners wrong while you first make progress on something that works at all. > 5. ptrace_report_clone() is racy. parent->parent can exit and untrace > child before utrace_attach_task(child, UTRACE_ATTACH_CREATE ...). This seems like it would only matter if we lack proper synchronization with whatever governs the tracer's list of tracees. Any of the kinds of attach ought to take the appropriate lock for that, no? > Anything else I missed? I don't know. I know more about what was wrong with the old patch than what wasn't right. I think it is now well past time to just get something going and see what you hit. We have the ptrace-tests suite for lots of behavior semantics tests. Run its 'make check' and see what pops out, and that should give you plenty to think about. Its 'make xcheck' is the torture tests for things like race conditions that you have been concentrating on. The issues like security check orders and such won't even be caught by those. But all of that you can leave to fester while we start to work on a clean implementation of the core functionality. Just don't poke those cases, and they won't poke you back. We can give them a fresh look in the context of some code we are happy(er) with in the other respects. > But again. I still have no idea how to fix the problems with > ptrace_detach(signr) which doesn't do UTRACE_DETACH. I suspect the extra-engine approach will be promising. > I am stuck. Break on through! Thanks, Roland From Srikar.Dronamraju at d23av02.au.ibm.com.redhat.com Tue Aug 11 14:52:11 2009 From: Srikar.Dronamraju at d23av02.au.ibm.com.redhat.com (Srikar.Dronamraju at d23av02.au.ibm.com.redhat.com) Date: Tue, 11 Aug 2009 20:22:11 +0530 Subject: resume from another engine results in loss of singlestep req. Message-ID: <20090811145211.GA30132@linux.vnet.ibm.com> Hi Roland, If we have two utrace engines for a thread with first engine requesting UTRACE_STOP and second one requesting UTRACE_SINGLESTEP, utrace correctly gives priority to UTRACE_STOP. However when the first engine detaches(or resumes) the singlestep request from the second engine is not given preference and the traced thread resumes instead of single stepping. The second engine doesnt even get a chance to re-assert singlestep. If this is expected behaviour, Is there a way for singlestep to be re-asserted from the second thread? I am attaching a tar file which has two simple utrace modules which can depict the problem. Please see run.sh for steps to see the problem that I am asking about. Also please refer my mail to utrace-devel here. https://www.redhat.com/archives/utrace-devel/2009-March/msg00006.html Then I had reported that on resume, I have noticied that singlestep being ignored. -- Thanks and Regards Srikar -------------- next part -------------- A non-text attachment was scrubbed... Name: trial.tgz Type: application/x-tar-gz Size: 1872 bytes Desc: not available URL: From oleg at redhat.com Tue Aug 11 17:00:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 11 Aug 2009 19:00:05 +0200 Subject: Q: ptrace_detach() && UTRACE_DETACH In-Reply-To: <20090811012521.6F8DD4259E@magilla.sf.frob.com> References: <20090806005735.GA21003@redhat.com> <20090807194541.1D3DF4213B@magilla.sf.frob.com> <20090810140355.GA7816@redhat.com> <20090811012521.6F8DD4259E@magilla.sf.frob.com> Message-ID: <20090811170005.GA14542@redhat.com> On 08/10, Roland McGrath wrote: > > > Anyway. I am not proud of this idea, and it needs more thinking in any case. > > I don't doubt that we can find a set of rules by which it can work. But > IMHO it's far better to keep it a very simple API rule that ->data belongs > entirely to the engine but no other field should be touched directly. > Of course, ptrace can always be a behind-the-curtain exception. > But whenever we can avoid that, we will. Agreed, but > Here's another idea. Don't ever leave the regular ptrace_ops engine > attached after PTRACE_DETACH. Instead, add another engine with a separate > ops vector and event mask, just for the parting signal case. That engine > is very simple: it only has to set UTRACE_EVENT(QUIESCE) implement the > callbacks to inject the parting signal (and handle the corner cases). I don't understand why this is better than just changing ->ops. Except, yes, I agree with above. Adding another engine during detach adds more complexity, UTRACE_ATTACH_CREATE can fail, we should create the new context for new_engine->data... But OK. Let's discuss this later. At least we both agree ptrace_attach() should not try to re-use the old engine, and detach should use a special ops vector (with old or new engine). This makes me feel a bit better. > > Other problems with attach/detach which are more or less simple: > > It sounds like you have fixes in mind. Just do them. OK, will do. > > 5. ptrace_report_clone() is racy. parent->parent can exit and untrace > > child before utrace_attach_task(child, UTRACE_ATTACH_CREATE ...). > > This seems like it would only matter if we lack proper synchronization > with whatever governs the tracer's list of tracees. Any of the kinds of > attach ought to take the appropriate lock for that, no? Can't understand... Just in case, I'll explain which race I meant. Suppose the freshly forked child should be ptraced. In that case ptrace_init_task(child) does ptrace_link() under write_lock(tasklist). Now ptrace_report_clone() should attach the ptrace_utrace_ops engine. But the tracer can exit and do ptrace_unlink(child) (in that case it also untraces current but this doesn't matter). If ptrace_report_clone() does ptrace_report_clone() after that, the child is not ptraced, but has ptrace_utrace_ops attached. > We have the ptrace-tests suite for lots of behavior semantics tests. > Run its 'make check' and see what pops out, and that should give you > plenty to think about. OK. I'll try to do some trivial fixups first, so that it will be possible to actually run and test the kernel with ptrace-over-utrace. Oleg. From oleg at redhat.com Tue Aug 11 17:23:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 11 Aug 2009 19:23:10 +0200 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090811145211.GA30132@linux.vnet.ibm.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> Message-ID: <20090811172310.GA14672@redhat.com> I don't know the answer, but I'd like to know it too ;) On 08/11, Srikar.Dronamraju at d23av02.au.ibm.com wrote: > > If we have two utrace engines for a thread with first engine requesting > UTRACE_STOP and second one requesting UTRACE_SINGLESTEP, utrace > correctly gives priority to UTRACE_STOP. > > However when the first engine detaches(or resumes) the singlestep > request from the second engine is not given preference and the traced > thread resumes instead of single stepping. The second engine doesnt > even get a chance to re-assert singlestep. Not only UTRACE_SINGLESTEP... UTRACE_REPORT can't be lost, we have utrace_report->reports. But what about UTRACE_INTERRUPT ? IOW, should any callback ever return (say) UTRACE_INTERRUPT instead of utrace_control(UTRACE_INTERRUPT) ? Oleg. From andre at votebrasil.com Tue Aug 11 19:32:07 2009 From: andre at votebrasil.com (=?iso-8859-1?B?Q2zhdWRpbw==?=) Date: Tue, 11 Aug 2009 16:32:07 -0300 Subject: =?iso-8859-1?q?Beba_Poesia_sem_modera=E7=E3o!?= Message-ID: <20090804.HHBXZDGCTCGNDEZD@votebrasil.com> Ol? se voc? aprecia poemas e contos... Acesse www.bebapoesia.blogspot.com Este v?deo ? s? um aperitivo... http://www.youtube.com/watch?v=YdmIHVkTqIc Para se deliciar com hist?rias curtas, acesse www.comacontos.blogspot.com Obrigado por sua aten??o! Cl?udio -------------- next part -------------- An HTML attachment was scrubbed... URL: From roland at redhat.com Tue Aug 11 20:10:24 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 11 Aug 2009 13:10:24 -0700 (PDT) Subject: resume from another engine results in loss of singlestep req. In-Reply-To: Srikar.Dronamraju@d23av02.au.ibm.com's message of Tuesday, 11 August 2009 20:22:11 +0530 <20090811145211.GA30132@linux.vnet.ibm.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> Message-ID: <20090811201024.95EE74259E@magilla.sf.frob.com> The intent is that if you asked for UTRACE_SINGLESTEP (or anything else but plain UTRACE_RESUME), you should be guaranteed another callback after a stop and resumption, i.e. after any time that the resume action you asked for was implicitly lost. Perhaps the following patch fixes it? Thanks, Roland diff --git a/kernel/utrace.c b/kernel/utrace.c index 954f9fe..0000000 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -1348,7 +1348,13 @@ static bool finish_callback(struct utrac spin_unlock(&utrace->lock); } } else { - if (action == UTRACE_REPORT) + /* + * If this engine asked for any particular resume + * action other than UTRACE_STOP, make sure it gets + * another callback on resumption in case another + * engine has us stop in this round. + */ + if (action < UTRACE_RESUME) report->reports = true; if (engine_wants_stop(engine)) { From roland at redhat.com Tue Aug 11 21:37:39 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 11 Aug 2009 14:37:39 -0700 (PDT) Subject: resume from another engine results in loss of singlestep req. In-Reply-To: Oleg Nesterov's message of Tuesday, 11 August 2009 19:23:10 +0200 <20090811172310.GA14672@redhat.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> Message-ID: <20090811213739.EA81A4259E@magilla.sf.frob.com> > Not only UTRACE_SINGLESTEP... UTRACE_REPORT can't be lost, we have > utrace_report->reports. But what about UTRACE_INTERRUPT ? > > IOW, should any callback ever return (say) UTRACE_INTERRUPT instead > of utrace_control(UTRACE_INTERRUPT) ? Indeed I think this is handled wrong in the current code. The intent is that if you return UTRACE_INTERRUPT, then after a resumption you will indeed get the interrupt effect (consistent with what I just told Srikar). This change replaces the one I just posted in response to Srikar's message. It compiles, but I haven't tested it or anything. I think this might be the right fix. First, we change the order so that UTRACE_INTERRUPT prevails over UTRACE_REPORT. (I'm really not sure why I ever had it the other way around.) Next, we keep track of not only whether one engine wanted a report when another wanted stop, but of the prevailing resume action (i.e. least value still > UTRACE_STOP). After stopping and resuming, we apply UTRACE_INTERRUPT or UTRACE_REPORT as needed to make sure we get the kind of resume report we need. What do you think? Thanks, Roland diff --git a/include/linux/utrace.h b/include/linux/utrace.h index 6b62c05..0000000 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h @@ -183,8 +183,8 @@ void task_utrace_proc_status(struct seq_ /** * enum utrace_resume_action - engine's choice of action for a traced task * @UTRACE_STOP: Stay quiescent after callbacks. - * @UTRACE_REPORT: Make some callback soon. * @UTRACE_INTERRUPT: Make @report_signal() callback soon. + * @UTRACE_REPORT: Make some callback soon. * @UTRACE_SINGLESTEP: Resume in user mode for one instruction. * @UTRACE_BLOCKSTEP: Resume in user mode until next branch. * @UTRACE_RESUME: Resume normally in user mode. @@ -199,8 +199,8 @@ void task_utrace_proc_status(struct seq_ */ enum utrace_resume_action { UTRACE_STOP, - UTRACE_REPORT, UTRACE_INTERRUPT, + UTRACE_REPORT, UTRACE_SINGLESTEP, UTRACE_BLOCKSTEP, UTRACE_RESUME, diff --git a/kernel/utrace.c b/kernel/utrace.c index 954f9fe..0000000 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -377,7 +377,7 @@ static inline bool finish_utrace_stop(st * engine may still want us to stay stopped. */ static bool utrace_stop(struct task_struct *task, struct utrace *utrace, - bool report) + enum utrace_resume_action action) { bool killed; @@ -401,7 +401,14 @@ static bool utrace_stop(struct task_stru return true; } - if (report) { + if (action == UTRACE_INTERRUPT) { + /* + * Ensure a %UTRACE_SIGNAL_REPORT reporting pass when we're + * resumed. The recalc_sigpending() call below will see + * this flag and set TIF_SIGPENDING. + */ + utrace->interrupt = 1; + } else if (action < UTRACE_RESUME) { /* * Ensure a reporting pass when we're resumed. */ @@ -1259,17 +1266,17 @@ EXPORT_SYMBOL_GPL(utrace_barrier); * This is local state used for reporting loops, perhaps optimized away. */ struct utrace_report { - enum utrace_resume_action action; u32 result; + enum utrace_resume_action action; + enum utrace_resume_action resume_action; bool detaches; - bool reports; bool takers; bool killed; }; #define INIT_REPORT(var) \ - struct utrace_report var = { UTRACE_RESUME, 0, \ - false, false, false, false } + struct utrace_report var = { 0, UTRACE_RESUME, UTRACE_RESUME, \ + false, false, false } /* * We are now making the report, so clear the flag saying we need one. @@ -1298,14 +1305,14 @@ static void finish_report(struct utrace_ { bool clean = (report->takers && !report->detaches); - if (report->action <= UTRACE_REPORT && !utrace->report) { - spin_lock(&utrace->lock); - utrace->report = 1; - set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); - } else if (report->action == UTRACE_INTERRUPT && !utrace->interrupt) { + if (report->action == UTRACE_INTERRUPT && !utrace->interrupt) { spin_lock(&utrace->lock); utrace->interrupt = 1; set_tsk_thread_flag(task, TIF_SIGPENDING); + } else if (report->action <= UTRACE_REPORT && !utrace->report) { + spin_lock(&utrace->lock); + utrace->report = 1; + set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); } else if (clean) { return; } else { @@ -1348,8 +1355,8 @@ static bool finish_callback(struct utrac spin_unlock(&utrace->lock); } } else { - if (action == UTRACE_REPORT) - report->reports = true; + if (action < report->resume_action) + report->resume_action = action; if (engine_wants_stop(engine)) { spin_lock(&utrace->lock); @@ -1709,7 +1716,8 @@ static void finish_resume_report(struct switch (report->action) { case UTRACE_STOP: - report->killed = utrace_stop(task, utrace, report->reports); + report->killed = utrace_stop(task, utrace, + report->resume_action); break; case UTRACE_INTERRUPT: From roland at redhat.com Tue Aug 11 22:05:56 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 11 Aug 2009 15:05:56 -0700 (PDT) Subject: Q: ptrace_detach() && UTRACE_DETACH In-Reply-To: Oleg Nesterov's message of Tuesday, 11 August 2009 19:00:05 +0200 <20090811170005.GA14542@redhat.com> References: <20090806005735.GA21003@redhat.com> <20090807194541.1D3DF4213B@magilla.sf.frob.com> <20090810140355.GA7816@redhat.com> <20090811012521.6F8DD4259E@magilla.sf.frob.com> <20090811170005.GA14542@redhat.com> Message-ID: <20090811220556.2002F4259E@magilla.sf.frob.com> > I don't understand why this is better than just changing ->ops. Except, > yes, I agree with above. Sure, if you think about the innards they amount to about the same thing. After PTRACE_DETACH, there is one engine attached and it uses the special ops vector. They are really just different ways to convince oneself that there are no problematic races. To change ->ops we have to convince ourselves from scratch (which indeed perhaps is not all that hard). > Adding another engine during detach adds more complexity, UTRACE_ATTACH_CREATE > can fail, we should create the new context for new_engine->data... It can only fail in pathological OOM situations (I think). There it's probably fine for PTRACE_DETACH to do something strange like yield and return -ERESTARTNOINTR. I'm not sure it needs any context structure. It could just store the signal number with engine->data=(void*)(unsigned long)signr (or just still use someplace else like task->exit_code). > But OK. Let's discuss this later. Agreed. > At least we both agree ptrace_attach() > should not try to re-use the old engine, and detach should use a special > ops vector (with old or new engine). This makes me feel a bit better. I think all three are plausible options. We'll just have to see what seems simplest and cleanest to cover all the corners (i.e. attach/detach races and such) affected by this choice. > Can't understand... Just in case, I'll explain which race I meant. > > Suppose the freshly forked child should be ptraced. In that case > ptrace_init_task(child) does ptrace_link() under write_lock(tasklist). Clearly this is not part of any clean implementation in the long run. In any pure utrace-based implementation, or IMHO even any one with only as much kludgery as ptrace semantics really demand (i.e. wait interference), all related bookkeeping would be driven from ptrace's report_clone hook. Thanks, Roland From srikar at linux.vnet.ibm.com Wed Aug 12 07:26:21 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 12 Aug 2009 12:56:21 +0530 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090811213739.EA81A4259E@magilla.sf.frob.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> Message-ID: <20090812072621.GB12098@linux.vnet.ibm.com> Hi Roland, Thanks for the quick patch. > I think this might be the right fix. First, we change the order so that > UTRACE_INTERRUPT prevails over UTRACE_REPORT. (I'm really not sure why I > ever had it the other way around.) Next, we keep track of not only whether > one engine wanted a report when another wanted stop, but of the prevailing > resume action (i.e. least value still > UTRACE_STOP). After stopping and > resuming, we apply UTRACE_INTERRUPT or UTRACE_REPORT as needed to make sure > we get the kind of resume report we need. I applied your patch. However it doesnt seem to fix the problem. i.e I see the program still continuing with resume and I dont see any more callbacks being made. ---------------------------------------------------------------------- In probe5_a init_module In probe5_b init_module In probe5_a engine_a_report_signal ffff880206ef9708 signr=5 action=35 ret=10 In probe5_a engine_a_report_signal ffff880206ef9948 signr=5 action=10 ret=13 In probe5_a cleanup_module --------------------------------------------------------------------- -- Thanks and Regards Srikar PS: Changes in probe5_a and probe5_b are 1. remove duplicate print statements in report_signal callbacks. 2. cache the return from report_signal and use it with utrace_resume_action in report_quiesce. i.e static u32 engine_a_report_quiesce(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *tsk, unsigned long event) { printk(KERN_INFO "In engine_a_report_quiesce with quiesce_action=%x\n", quiesce_action); return utrace_resume_action(quiesce_action); } * Roland McGrath [2009-08-11 14:37:39]: From ananth at in.ibm.com Wed Aug 12 10:15:24 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Wed, 12 Aug 2009 15:45:24 +0530 Subject: ptrace/utrace branch/tree? Message-ID: <20090812101524.GC4343@in.ibm.com> Oleg, >From conversations between you and Roland, it looks like you're reworking quite a bit of the ptrace/utrace code. Wondering if you are hosting your changes in a git tree/branch? Regards, Ananth From oleg at redhat.com Wed Aug 12 10:36:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 12 Aug 2009 12:36:44 +0200 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090811213739.EA81A4259E@magilla.sf.frob.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> Message-ID: <20090812103644.GA29939@redhat.com> On 08/11, Roland McGrath wrote: > > I think this might be the right fix. First, we change the order so that > UTRACE_INTERRUPT prevails over UTRACE_REPORT. (I'm really not sure why I > ever had it the other way around.) and this is consistent with the behaviour utrace_resume() which does nothing if utrace->interrupt == T, it just returns and relies on utrace_get_signal(). But I wonder if this always correct, please see below. > Next, we keep track of not only whether > one engine wanted a report when another wanted stop, but of the prevailing > resume action (i.e. least value still > UTRACE_STOP). After stopping and > resuming, we apply UTRACE_INTERRUPT or UTRACE_REPORT as needed to make sure > we get the kind of resume report we need. Agreed, this looks like a right change to me. In any case I think this makes the code more understandable and logical, and ->resume_action is much better than ->reports imho. But, you seem to forget to fix other callers of utrace_stop(), utrace_report_syscall_entry utrace_finish_vfork utrace_report_exit they all do utrace_stop(false), and with this change this "false" means UTRACE_STOP. > @@ -1298,14 +1305,14 @@ static void finish_report(struct utrace_ > { > bool clean = (report->takers && !report->detaches); > > - if (report->action <= UTRACE_REPORT && !utrace->report) { > - spin_lock(&utrace->lock); > - utrace->report = 1; > - set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); > - } else if (report->action == UTRACE_INTERRUPT && !utrace->interrupt) { > + if (report->action == UTRACE_INTERRUPT && !utrace->interrupt) { > spin_lock(&utrace->lock); > utrace->interrupt = 1; > set_tsk_thread_flag(task, TIF_SIGPENDING); > + } else if (report->action <= UTRACE_REPORT && !utrace->report) { > + spin_lock(&utrace->lock); > + utrace->report = 1; > + set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); Can't we (well, partly) miss UTRACE_STOP request? Two engines A and B. Say, utrace_report_exec() calls ->report_exec(). A returns UTRACE_STOP, B returns UTRACE_INTERRUPT. ->resume_action = UTRACE_INTERRUPT, finish_report() sets ->interrupt = 1, utrace_report_exec() returns. Now. We can't rely on utrace_resume()->finish_resume_report() which can notice the stop request and do utrace_stop() to actually stop. This is delayed until utrace_get_signal()->finish_resume_report(), and I am not sure this is what we really want: - minor, but it is possible that tracehook_notify_jctl() will be called before tracehook_get_signal(). Not a real problem, but shouldn't UTRACE_STOP mean "stop as soon as possible" ? - utrace_get_signal() can return without finish_resume_report() if B->report_signal() (say) returns UTRACE_SIGNAL_DELIVER. Yes, in this case A->report_signal() can return UTRACE_STOP again, this means utrace_get_signal() returns with ->report = T. But another UTRACE_INTERRUPT can set ->interrupt, this can "disable" ->report again, and so on. In short: unless I missed something, it is hardly possible to predict when the tracee will actually stop, perhaps UTRACE_STOP needs more respect? Oleg. From oleg at redhat.com Wed Aug 12 11:22:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 12 Aug 2009 13:22:54 +0200 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090811213739.EA81A4259E@magilla.sf.frob.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> Message-ID: <20090812112254.GA32402@redhat.com> On 08/11, Roland McGrath wrote: > > @@ -1298,14 +1305,14 @@ static void finish_report(struct utrace_ > { > bool clean = (report->takers && !report->detaches); > > - if (report->action <= UTRACE_REPORT && !utrace->report) { > - spin_lock(&utrace->lock); > - utrace->report = 1; > - set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); > - } else if (report->action == UTRACE_INTERRUPT && !utrace->interrupt) { > + if (report->action == UTRACE_INTERRUPT && !utrace->interrupt) { > spin_lock(&utrace->lock); > utrace->interrupt = 1; > set_tsk_thread_flag(task, TIF_SIGPENDING); > + } else if (report->action <= UTRACE_REPORT && !utrace->report) { > + spin_lock(&utrace->lock); > + utrace->report = 1; Hmm. I think this is not exacly right. Suppose that report->action == UTRACE_INTERRUPT but utrace->interrupt is already set. In that case, since UTRACE_INTERRUPT <= UTRACE_REPORT, we set ->report. Not really bad, but not right anyway. Oleg. From oleg at redhat.com Wed Aug 12 11:28:15 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 12 Aug 2009 13:28:15 +0200 Subject: ptrace/utrace branch/tree? In-Reply-To: <20090812101524.GC4343@in.ibm.com> References: <20090812101524.GC4343@in.ibm.com> Message-ID: <20090812112815.GA32608@redhat.com> Hi Ananth, On 08/12, Ananth N Mavinakayanahalli wrote: > > From conversations between you and Roland, it looks like you're > reworking quite a bit of the ptrace/utrace code. Heh ;) I am glad that at least it _looks_ like I am doing some real work. Not yet. I'll CC you when I have any useful patches/changes. Oleg. From oleg at redhat.com Wed Aug 12 12:32:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 12 Aug 2009 14:32:51 +0200 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090812072621.GB12098@linux.vnet.ibm.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812072621.GB12098@linux.vnet.ibm.com> Message-ID: <20090812123251.GA2039@redhat.com> On 08/12, Srikar Dronamraju wrote: > > Thanks for the quick patch. > > > I think this might be the right fix. First, we change the order so that > > UTRACE_INTERRUPT prevails over UTRACE_REPORT. (I'm really not sure why I > > ever had it the other way around.) Next, we keep track of not only whether > > one engine wanted a report when another wanted stop, but of the prevailing > > resume action (i.e. least value still > UTRACE_STOP). After stopping and > > resuming, we apply UTRACE_INTERRUPT or UTRACE_REPORT as needed to make sure > > we get the kind of resume report we need. > > I applied your patch. However it doesnt seem to fix the problem. > i.e I see the program still continuing with resume and I dont see any > more callbacks being made. > > ---------------------------------------------------------------------- > In probe5_a init_module > In probe5_b init_module > In probe5_a engine_a_report_signal ffff880206ef9708 signr=5 action=35 ret=10 > In probe5_a engine_a_report_signal ffff880206ef9948 signr=5 action=10 ret=13 > In probe5_a cleanup_module > --------------------------------------------------------------------- > > -- > Thanks and Regards > Srikar > > PS: Changes in probe5_a and probe5_b are > 1. remove duplicate print statements in report_signal callbacks. > 2. cache the return from report_signal and use it with > utrace_resume_action in report_quiesce. Could you show the code please? I don't really understand how it looks with 1+2 above. But, just in case... I think module_b should re-assert SINGLESTEP from either report_quiesce/report_signal. Btw. Roland, unless utrace_get_signal() does dequeue_signal(info), we pass a random value in info->si_signo to ->report_signal(). Yes, _if_ I understand correctly, report_signal can check action, but perhaps it makes sense to set ->si_signo = 0, this may help to engine writers. For example, probe5_a and probe5_b just blindly check ->si_signo. Oleg. From srikar at linux.vnet.ibm.com Wed Aug 12 13:18:43 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 12 Aug 2009 18:48:43 +0530 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090812123251.GA2039@redhat.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812072621.GB12098@linux.vnet.ibm.com> <20090812123251.GA2039@redhat.com> Message-ID: <20090812131843.GC12098@linux.vnet.ibm.com> > > Could you show the code please? I don't really understand how it > looks with 1+2 above. > I am attaching the code. The module code is in try_utrace/probe5_a.c and try_utrace/probe5_b.c. > But, just in case... I think module_b should re-assert SINGLESTEP > from either report_quiesce/report_signal. Yes I have re-asserted SINGLESTEP. I also have printk's in report_quiesce/report_signal to see if report_quiesce/report_signal in probe5_b are called after we do utrace_control(.,,UTRACE_RESUME/UTRACE_DETACH). However those callbacks dont seem to be called again. -- Thanks and Regards Srikar -------------- next part -------------- A non-text attachment was scrubbed... Name: trial2.tgz Type: application/x-tar-gz Size: 1977 bytes Desc: not available URL: From oleg at redhat.com Wed Aug 12 13:46:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 12 Aug 2009 15:46:40 +0200 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090812112254.GA32402@redhat.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812112254.GA32402@redhat.com> Message-ID: <20090812134640.GA6100@redhat.com> On 08/12, Oleg Nesterov wrote: > > On 08/11, Roland McGrath wrote: > > > > @@ -1298,14 +1305,14 @@ static void finish_report(struct utrace_ > > { > > bool clean = (report->takers && !report->detaches); > > > > - if (report->action <= UTRACE_REPORT && !utrace->report) { > > - spin_lock(&utrace->lock); > > - utrace->report = 1; > > - set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); > > - } else if (report->action == UTRACE_INTERRUPT && !utrace->interrupt) { > > + if (report->action == UTRACE_INTERRUPT && !utrace->interrupt) { > > spin_lock(&utrace->lock); > > utrace->interrupt = 1; > > set_tsk_thread_flag(task, TIF_SIGPENDING); > > + } else if (report->action <= UTRACE_REPORT && !utrace->report) { > > + spin_lock(&utrace->lock); > > + utrace->report = 1; > > Hmm. I think this is not exacly right. Suppose that > report->action == UTRACE_INTERRUPT but utrace->interrupt is already set. > In that case, since UTRACE_INTERRUPT <= UTRACE_REPORT, we set ->report. > > Not really bad, but not right anyway. I'd suggest: static void finish_report(struct utrace_report *report, struct task_struct *task, struct utrace *utrace) { if (report->action <= UTRACE_REPORT) { bool intr = (report->action == UTRACE_INTERRUPT); if (!(intr ? utrace->interrupt : utrace->report)) { spin_lock(&utrace->lock); if (intr) { utrace->interrupt = true; set_tsk_thread_flag(task, TIF_SIGPENDING); } else { utrace->report = true; set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); } spin_unlock(&utrace->lock); } } if (likely(report->takers && !report->detaches)) return; spin_lock(&utrace->lock); utrace_reset(task, utrace, &report->action); } personally, I don't think it makes sense to try to save one spin_lock() like the current code does. utrace_reset() is unlikely case. But we can do static void finish_report(struct utrace_report *report, struct task_struct *task, struct utrace *utrace) { bool clean = (report->takers && !report->detaches); if (report->action <= UTRACE_REPORT) { bool intr = (report->action == UTRACE_INTERRUPT); if (!(intr ? utrace->interrupt : utrace->report)) { spin_lock(&utrace->lock); if (intr) { utrace->interrupt = true; set_tsk_thread_flag(task, TIF_SIGPENDING); } else { utrace->report = true; set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); } if (unlikely(!clean)) goto reset; spin_unlock(&utrace->lock); } } if (likely(clean)) return; spin_lock(&utrace->lock); reset: utrace_reset(task, utrace, &report->action); } Oleg. From oleg at redhat.com Wed Aug 12 15:56:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 12 Aug 2009 17:56:24 +0200 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090812131843.GC12098@linux.vnet.ibm.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812072621.GB12098@linux.vnet.ibm.com> <20090812123251.GA2039@redhat.com> <20090812131843.GC12098@linux.vnet.ibm.com> Message-ID: <20090812155624.GA27975@redhat.com> On 08/12, Srikar Dronamraju wrote: > > > > Could you show the code please? I don't really understand how it > > looks with 1+2 above. > > > > I am attaching the code. > The module code is in try_utrace/probe5_a.c and try_utrace/probe5_b.c. > > > But, just in case... I think module_b should re-assert SINGLESTEP > > from either report_quiesce/report_signal. > > Yes I have re-asserted SINGLESTEP. > I also have printk's in report_quiesce/report_signal to see if > report_quiesce/report_signal in probe5_b are called after we do > utrace_control(.,,UTRACE_RESUME/UTRACE_DETACH). > > However those callbacks dont seem to be called again. Aaaaaaahhh. Srikar, I spent 3 hours trying to understand.... Your code does NOT reassert SINGLESTEP. Of course, ->report_signal is not called again, utrace_get_signal() just clears ->report when it is called after wakeup. Because you forgot to add QUIESCE to utrace_set_events's mask !!! This means: 1. ->report_quiesce() is never called 2. utrace_get_signal() won't call ->report_signal() utrace_get_signal: if (... || utrace->report || ...) { ... utrace->report = 0; event = 0; } ... list_for_each_entry(engine, &utrace->attached, entry) { ... if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) continue; ... ops->report_signal(...); } Oleg. From srikar at linux.vnet.ibm.com Wed Aug 12 17:20:12 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 12 Aug 2009 22:50:12 +0530 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090812155624.GA27975@redhat.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812072621.GB12098@linux.vnet.ibm.com> <20090812123251.GA2039@redhat.com> <20090812131843.GC12098@linux.vnet.ibm.com> <20090812155624.GA27975@redhat.com> Message-ID: <20090812172012.GD12098@linux.vnet.ibm.com> > > Aaaaaaahhh. Srikar, I spent 3 hours trying to understand.... > > Your code does NOT reassert SINGLESTEP. Of course, ->report_signal > is not called again, utrace_get_signal() just clears ->report when > it is called after wakeup. > > Because you forgot to add QUIESCE to utrace_set_events's mask !!! > Oh Sorry for the trouble. Yes setting QUIESCE in utrace_set_events makes it work. -- Thanks and Regards Srikar From oleg at redhat.com Wed Aug 12 18:05:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 12 Aug 2009 20:05:37 +0200 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090812172012.GD12098@linux.vnet.ibm.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812072621.GB12098@linux.vnet.ibm.com> <20090812123251.GA2039@redhat.com> <20090812131843.GC12098@linux.vnet.ibm.com> <20090812155624.GA27975@redhat.com> <20090812172012.GD12098@linux.vnet.ibm.com> Message-ID: <20090812180537.GA11182@redhat.com> On 08/12, Srikar Dronamraju wrote: > > Yes setting QUIESCE in utrace_set_events makes > it work. Great. But please don't forget that engine_b_report_signal() which does if (signr == SIGTRAP) ret = UTRACE_SINGLESTEP | ... is not right, please see my previous email about "random" value in ->si_signo. With your test-case, it could be SIGTRAP just because it was SIGTRAP when utrace_get_signal() was called after run.sh does kill -s 5. And UTRACE_SINGLESTEP above can provoke another SIGTRAP from syscall_trace_leave(). Oleg. From hot-deals at clubvacationdeals.com Thu Aug 13 02:43:04 2009 From: hot-deals at clubvacationdeals.com (Club Vacation Deals) Date: Wed, 12 Aug 2009 22:43:04 -0400 Subject: The new vacation concept Message-ID: <4f533a64403348891c018ff7a5739cdf@www.vallarta-paradise.com> An HTML attachment was scrubbed... URL: From contato at autoemoferta.com.br Thu Aug 13 08:27:42 2009 From: contato at autoemoferta.com.br (Praça Shopping) Date: Thu, 13 Aug 2009 08:27:42 AM -0300 Subject: Coloque seu Pai em Primeiro Lugar! Message-ID: <200908131632.n7DGWsex005511@mx1.redhat.com> -------------- next part -------------- An HTML attachment was scrubbed... URL: From streetcars at aceunico.com Thu Aug 13 16:46:23 2009 From: streetcars at aceunico.com (Hortillosa) Date: Thu, 13 Aug 2009 18:46:23 +0200 Subject: skeletonises Message-ID: D at the cottage very soon after you, and were so thankful to find you there." "Is--is _everybody_ well?" Again that faint flush showed on the cheeks; but Edie was mercifully blind, and answered with direct simplicity-- "Every one, dear, and you are going to be quite well, too. You must not talk any more just now, for you are rather a weak little girl still. Drink this cup of milk, and roll over, and have another nap. It is good to see you sleeping quietly and peacefully again. There! Shut your eyes, like a good girl!" Then once more Margot floated off into unconsciousness; but this time it was the blessed, health-restoring unconsciousness of sleep, such sleep as she had not known for days past, and from which she awoke with rested body and clearer brain. When the dear father came in to kiss and greet her, a thin white hand crept up to stroke his hair, and pull his ear in the way he loved, whereupon he blinked away tears of thankfulness, and essayed to be fierce and reproachful. "So you couldn't be satisfied until you had dragged the whole family after you, to the ends of the earth! There's no pleasing some people. This is my reward for being such a fool as to think you could take care of yourself!" "Ducky Doodles!" murmured Margot fondly. As of yore, she manifested not the faintest alarm at his pretence of severity, but twitched his ear with complacent composure, and once more Mr Vane blinked and swallowed a lump in his throat. There had been hours during those last days when he had feared that he might never again hear himself called "Ducky Doodles," and what a sad grey world that would have meant! Then came Ron, a little embarrassed, as was natural in a lad of his years, b -------------- next part -------------- A non-text attachment was scrubbed... Name: breakdown.jpg Type: image/jpeg Size: 31978 bytes Desc: not available URL: From oleg at redhat.com Thu Aug 13 17:12:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 13 Aug 2009 19:12:12 +0200 Subject: [PATCH 00/6] utrace-ptrace: initial changes Message-ID: <20090813171212.GA29074@redhat.com> Some very basic changes to start the re-work. Oleg. From oleg at redhat.com Thu Aug 13 17:12:14 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 13 Aug 2009 19:12:14 +0200 Subject: [PATCH 01] remove (almost all) !CONFIG_UTRACE_PTRACE code Message-ID: <20090813171214.GA29082@redhat.com> On top of http://people.redhat.com/roland/utrace/2.6-current/utrace-ptrace.patch We need a starting point: a patch which at least partly works. To discuss the actual changes, to have the ability to test things, etc. But, due to discussed task_ptrace() problems, the patch above can't work in any way. So I just removed the old code for now. With this patch the kernel boots, but ptrace is not useable: the kernel crashes very quickly during 'make check' (ptrace-tests). It crashes on "random" test, usually 3-5 is enough. I spent some time trying to investigate, but then decided it doesn't make sense _now_. I suspect, the partly-detach logic is the main offender. We will see. --- include/linux/ptrace.h | 41 ----------- include/linux/tracehook.h | 40 ----------- kernel/ptrace.c | 163 ---------------------------------------------- kernel/utrace.c | 15 ---- 4 files changed, 2 insertions(+), 257 deletions(-) --- PU/include/linux/ptrace.h~01_REMOVE_OLD_CODE 2009-08-11 16:54:21.000000000 +0200 +++ PU/include/linux/ptrace.h 2009-08-13 15:19:18.000000000 +0200 @@ -120,7 +120,6 @@ static inline void ptrace_unlink(struct int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data); int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data); -#ifndef CONFIG_UTRACE_PTRACE /** * task_ptrace - return %PT_* flags that apply to a task * @task: pointer to &task_struct in question @@ -132,48 +131,8 @@ static inline int task_ptrace(struct tas return task->ptrace; } -/** - * ptrace_event - possibly stop for a ptrace event notification - * @mask: %PT_* bit to check in @current->ptrace - * @event: %PTRACE_EVENT_* value to report if @mask is set - * @message: value for %PTRACE_GETEVENTMSG to return - * - * This checks the @mask bit to see if ptrace wants stops for this event. - * If so we stop, reporting @event and @message to the ptrace parent. - * - * Returns nonzero if we did a ptrace notification, zero if not. - * - * Called without locks. - */ -static inline int ptrace_event(int mask, int event, unsigned long message) -{ - if (mask && likely(!(current->ptrace & mask))) - return 0; - current->ptrace_message = message; - ptrace_notify((event << 8) | SIGTRAP); - return 1; -} - -static inline void ptrace_utrace_exit(struct task_struct *task) -{ -} - -#else /* CONFIG_UTRACE_PTRACE */ - -static inline int task_ptrace(struct task_struct *task) -{ - return 0; -} - -static inline int ptrace_event(int mask, int event, unsigned long message) -{ - return 0; -} - extern void ptrace_utrace_exit(struct task_struct *); -#endif /* !CONFIG_UTRACE_PTRACE */ - /** * ptrace_init_task - initialize ptrace state for a new child * @child: new child task --- PU/include/linux/tracehook.h~01_REMOVE_OLD_CODE 2009-08-11 16:54:21.000000000 +0200 +++ PU/include/linux/tracehook.h 2009-08-13 15:50:27.000000000 +0200 @@ -69,29 +69,6 @@ static inline int tracehook_expect_break return (task_ptrace(task) & PT_PTRACED) != 0; } -/* - * ptrace report for syscall entry and exit looks identical. - */ -static inline void ptrace_report_syscall(struct pt_regs *regs) -{ - int ptrace = task_ptrace(current); - - if (!(ptrace & PT_PTRACED)) - return; - - ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); - - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} - /** * tracehook_report_syscall_entry - task is about to attempt a system call * @regs: user register state of current task @@ -117,7 +94,6 @@ static inline __must_check int tracehook if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && utrace_report_syscall_entry(regs)) return 1; - ptrace_report_syscall(regs); return 0; } @@ -142,7 +118,6 @@ static inline void tracehook_report_sysc { if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) utrace_report_syscall_exit(regs); - ptrace_report_syscall(regs); } /** @@ -156,7 +131,7 @@ static inline void tracehook_report_sysc static inline int tracehook_unsafe_exec(struct task_struct *task) { int unsafe = 0; - int ptrace = task->ptrace; + int ptrace = task_ptrace(task); if (ptrace & PT_PTRACED) { if (ptrace & PT_PTRACE_CAP) unsafe |= LSM_UNSAFE_PTRACE_CAP; @@ -179,7 +154,7 @@ static inline int tracehook_unsafe_exec( */ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk) { - if (tsk->ptrace & PT_PTRACED) + if (task_ptrace(tsk) & PT_PTRACED) return rcu_dereference(tsk->parent); return NULL; } @@ -204,9 +179,6 @@ static inline void tracehook_report_exec { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) utrace_report_exec(fmt, bprm, regs); - if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && - unlikely(task_ptrace(current) & PT_PTRACED)) - send_sig(SIGTRAP, current, 0); } /** @@ -223,7 +195,6 @@ static inline void tracehook_report_exit { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) utrace_report_exit(exit_code); - ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); if (unlikely(!list_empty(¤t->ptraced))) ptrace_utrace_exit(current); } @@ -330,8 +301,6 @@ static inline void tracehook_report_clon if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) && (clone_flags & CLONE_VFORK)) utrace_finish_vfork(current); - if (unlikely(trace)) - ptrace_event(0, trace, pid); } /** @@ -349,7 +318,6 @@ static inline void tracehook_report_clon static inline void tracehook_report_vfork_done(struct task_struct *child, pid_t pid) { - ptrace_event(PT_TRACE_VFORK_DONE, PTRACE_EVENT_VFORK_DONE, pid); } /** @@ -403,10 +371,6 @@ static inline void tracehook_signal_hand { if (task_utrace_flags(current)) utrace_signal_handler(current, stepping); -#ifndef CONFIG_UTRACE_PTRACE - if (stepping) - ptrace_notify(SIGTRAP); -#endif } /** --- PU/kernel/ptrace.c~01_REMOVE_OLD_CODE 2009-08-11 16:54:21.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-13 15:34:29.000000000 +0200 @@ -38,46 +38,6 @@ void __ptrace_link(struct task_struct *c child->parent = new_parent; } -#ifndef CONFIG_UTRACE_PTRACE -/* - * Turn a tracing stop into a normal stop now, since with no tracer there - * would be no way to wake it up with SIGCONT or SIGKILL. If there was a - * signal sent that would resume the child, but didn't because it was in - * TASK_TRACED, resume it now. - * Requires that irqs be disabled. - */ -static void ptrace_untrace(struct task_struct *child) -{ - spin_lock(&child->sighand->siglock); - if (task_is_traced(child)) { - /* - * If the group stop is completed or in progress, - * this thread was already counted as stopped. - */ - if (child->signal->flags & SIGNAL_STOP_STOPPED || - child->signal->group_stop_count) - __set_task_state(child, TASK_STOPPED); - else - signal_wake_up(child, 1); - } - spin_unlock(&child->sighand->siglock); -} - -static void ptrace_finish(struct task_struct *child) -{ - if (task_is_traced(child)) - ptrace_untrace(child); -} - -static void ptrace_detach_task(struct task_struct *child, int sig) -{ - /* Architecture-specific hardware disable .. */ - ptrace_disable(child); - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -} - -#else /* CONFIG_UTRACE_PTRACE */ - static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */ static void ptrace_detach_task(struct task_struct *child, int sig) @@ -119,12 +79,6 @@ void ptrace_utrace_exit(struct task_stru read_unlock(&tasklist_lock); } -static void ptrace_finish(struct task_struct *child) -{ -} - -#endif /* !CONFIG_UTRACE_PTRACE */ - /* * unptrace a task: move it back to its original parent and * remove it from the ptrace list. @@ -140,72 +94,11 @@ void __ptrace_unlink(struct task_struct list_del_init(&child->ptrace_entry); arch_ptrace_untrace(child); - ptrace_finish(child); -} - -#ifndef CONFIG_UTRACE_PTRACE - -/* - * Check that we have indeed attached to the thing.. - */ -int ptrace_check_attach(struct task_struct *child, int kill) -{ - int ret = -ESRCH; - - /* - * We take the read lock around doing both checks to close a - * possible race where someone else was tracing our child and - * detached between these two checks. After this locked check, - * we are sure that this is our traced child and that can only - * be changed by us so it's not changing right after this. - */ - read_lock(&tasklist_lock); - if ((child->ptrace & PT_PTRACED) && child->parent == current) { - ret = 0; - /* - * child->sighand can't be NULL, release_task() - * does ptrace_unlink() before __exit_signal(). - */ - spin_lock_irq(&child->sighand->siglock); - if (task_is_stopped(child)) - child->state = TASK_TRACED; - else if (!task_is_traced(child) && !kill) - ret = -ESRCH; - spin_unlock_irq(&child->sighand->siglock); - } - read_unlock(&tasklist_lock); - - if (!ret && !kill) - ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH; - - /* All systems go.. */ - return ret; -} - -static struct utrace_engine *prepare_ptrace_attach( - struct task_struct *child, struct task_struct *parent) -{ - return NULL; -} - -static int finish_ptrace_attach(struct task_struct *task, - struct utrace_engine *engine, - int retval) -{ - return retval; } static int ptrace_update_utrace(struct task_struct *task, struct utrace_engine *engine) { - return 0; -} - -#else /* CONFIG_UTRACE_PTRACE */ - -static int ptrace_update_utrace(struct task_struct *task, - struct utrace_engine *engine) -{ unsigned long events; /* @@ -702,8 +595,6 @@ int ptrace_check_attach(struct task_stru return ret; } -#endif /* !CONFIG_UTRACE_PTRACE */ - int __ptrace_may_access(struct task_struct *task, unsigned int mode) { const struct cred *cred = current_cred(), *tcred; @@ -751,21 +642,6 @@ bool ptrace_may_access(struct task_struc return !err; } -#ifdef CONFIG_UTRACE_PTRACE -static inline bool exclude_ptrace(struct task_struct *task) -{ - return false; -} -#else -/* - * For experimental use of utrace, exclude ptrace on the same task. - */ -static inline bool exclude_ptrace(struct task_struct *task) -{ - return unlikely(!!task_utrace_flags(task)); -} -#endif - int ptrace_attach(struct task_struct *task) { int retval; @@ -794,8 +670,6 @@ int ptrace_attach(struct task_struct *ta task_lock(task); retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); - if (!retval && exclude_ptrace(task)) - retval = -EBUSY; task_unlock(task); if (retval) goto unlock_creds; @@ -1087,42 +961,6 @@ static int ptrace_setsiginfo(struct task #define is_sysemu_singlestep(request) 0 #endif -#ifndef CONFIG_UTRACE_PTRACE -static int ptrace_resume(struct task_struct *child, long request, long data) -{ - if (!valid_signal(data)) - return -EIO; - - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - -#ifdef TIF_SYSCALL_EMU - if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) - set_tsk_thread_flag(child, TIF_SYSCALL_EMU); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); -#endif - - if (is_singleblock(request)) { - if (unlikely(!arch_has_block_step())) - return -EIO; - user_enable_block_step(child); - } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { - if (unlikely(!arch_has_single_step())) - return -EIO; - user_enable_single_step(child); - } else { - user_disable_single_step(child); - } - - child->exit_code = data; - wake_up_process(child); - - return 0; -} -#else /* CONFIG_UTRACE_PTRACE */ static int ptrace_resume(struct task_struct *child, long request, long data) { struct utrace_engine *engine; @@ -1285,7 +1123,6 @@ static int ptrace_resume(struct task_str return ret; } -#endif /* !CONFIG_UTRACE_PTRACE */ int ptrace_request(struct task_struct *child, long request, long addr, long data) --- PU/kernel/utrace.c~01_REMOVE_OLD_CODE 2009-08-11 16:54:21.000000000 +0200 +++ PU/kernel/utrace.c 2009-08-13 15:10:55.000000000 +0200 @@ -107,21 +107,6 @@ static struct utrace_engine *matching_en return NULL; } -#ifdef CONFIG_UTRACE_PTRACE -static inline bool exclude_utrace(struct task_struct *task) -{ - return false; -} -#else -/* - * For experimental use, utrace attach is mutually exclusive with ptrace. - */ -static inline bool exclude_utrace(struct task_struct *task) -{ - return unlikely(!!task->ptrace); -} -#endif - /* * Called without locks, when we might be the first utrace engine to attach. * If this is a newborn thread and we are not the creator, we have to wait From oleg at redhat.com Thu Aug 13 17:12:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 13 Aug 2009 19:12:17 +0200 Subject: [PATCH 02] ptrace_check_attach: check child->parent Message-ID: <20090813171217.GA29085@redhat.com> ptrace_check_attach() forgets to check we are the tracer, check ->parent. We can do this without tasklist_lock. --- --- PU/kernel/ptrace.c~02_CHECK_ATTACH 2009-08-13 15:34:29.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-13 17:04:49.000000000 +0200 @@ -576,6 +576,9 @@ int ptrace_check_attach(struct task_stru struct utrace_examiner exam; int ret; + if (child->parent != current) + return -ESRCH; + engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, &ptrace_utrace_ops, NULL); if (IS_ERR(engine)) From oleg at redhat.com Thu Aug 13 17:12:19 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 13 Aug 2009 19:12:19 +0200 Subject: [PATCH 03] ptrace_resume()->send_sig() can crash Message-ID: <20090813171219.GA29088@redhat.com> ptrace_resume()->send_sig() can hit the dead task without ->signal. Add the temporary fix. This change should be reverted later, signals-introduce-do_send_sig_info-helper.patch in -mm tree fixes this problem "by accident". Until then, make sure at least this bug won't add a noise during the testing. --- --- PU/kernel/ptrace.c~03_SEND_SIG 2009-08-13 17:04:49.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-13 17:35:29.000000000 +0200 @@ -1052,8 +1052,13 @@ static int ptrace_resume(struct task_str * After a syscall stop, @data is treated specially. * It just queues the signal. */ - if (data) - send_sig(data, child, 1); + if (data) { + /* XXX: until do_send_sig_info() */ + read_lock(&tasklist_lock); + if (child->signal) + send_sig(data, child, 1); + read_unlock(&tasklist_lock); + } data = 0; event = 0; break; From oleg at redhat.com Thu Aug 13 17:12:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 13 Aug 2009 19:12:21 +0200 Subject: [PATCH 04] shift ptrace_utrace_exit() from tracehook_report_exit() to exit_ptrace() Message-ID: <20090813171221.GA29095@redhat.com> tracehook_report_exit() calls ptrace_utrace_exit() to early. We don't have PF_EXITING yet, we can race with ptrace_traceme(). Granted, exit_ptrace/ptrace_utrace_exit should be reworked later. Just a minimal fix for now. --- include/linux/ptrace.h | 2 -- include/linux/tracehook.h | 2 -- kernel/ptrace.c | 20 +++++++++++--------- 3 files changed, 11 insertions(+), 13 deletions(-) --- PU/include/linux/ptrace.h~04_PTRACE_EXIT 2009-08-13 15:19:18.000000000 +0200 +++ PU/include/linux/ptrace.h 2009-08-13 17:53:02.000000000 +0200 @@ -131,8 +131,6 @@ static inline int task_ptrace(struct tas return task->ptrace; } -extern void ptrace_utrace_exit(struct task_struct *); - /** * ptrace_init_task - initialize ptrace state for a new child * @child: new child task --- PU/include/linux/tracehook.h~04_PTRACE_EXIT 2009-08-13 15:50:27.000000000 +0200 +++ PU/include/linux/tracehook.h 2009-08-13 17:51:52.000000000 +0200 @@ -195,8 +195,6 @@ static inline void tracehook_report_exit { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) utrace_report_exit(exit_code); - if (unlikely(!list_empty(¤t->ptraced))) - ptrace_utrace_exit(current); } /** --- PU/kernel/ptrace.c~04_PTRACE_EXIT 2009-08-13 17:35:29.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-13 17:55:13.000000000 +0200 @@ -70,15 +70,6 @@ static void ptrace_detach_task(struct ta utrace_engine_put(engine); } -void ptrace_utrace_exit(struct task_struct *task) -{ - struct task_struct *child; - read_lock(&tasklist_lock); - list_for_each_entry(child, &task->ptraced, ptrace_entry) - ptrace_detach_task(child, 0); - read_unlock(&tasklist_lock); -} - /* * unptrace a task: move it back to its original parent and * remove it from the ptrace list. @@ -810,6 +801,15 @@ int ptrace_detach(struct task_struct *ch return 0; } +static void ptrace_utrace_exit(struct task_struct *task) +{ + struct task_struct *child; + read_lock(&tasklist_lock); + list_for_each_entry(child, &task->ptraced, ptrace_entry) + ptrace_detach_task(child, 0); + read_unlock(&tasklist_lock); +} + /* * Detach all tasks we were using ptrace on. */ @@ -818,6 +818,8 @@ void exit_ptrace(struct task_struct *tra struct task_struct *p, *n; LIST_HEAD(ptrace_dead); + ptrace_utrace_exit(tracer); + write_lock_irq(&tasklist_lock); list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) { if (__ptrace_detach(tracer, p)) From oleg at redhat.com Thu Aug 13 17:12:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 13 Aug 2009 19:12:24 +0200 Subject: [PATCH 05] ptrace_detach_task: always do UTRACE_DETACH Message-ID: <20090813171224.GA29098@redhat.com> The current logic does not work. Remove it. Now detach always does UTRACE_DETACH and attach doesn't try to reuse the old engine. This means ptrace_detach(sig) can't work correctly. But, before we fix this problem, it is better to make other changes. In particular, it makes sense to move ->last_siginfo and ->exit_code to engine->data. As for ->exit_code, I mean that ptrace.c should not use ->exit_code at all, instead we should have a member in engine->data. --- --- PU/kernel/ptrace.c~05_ALWAYS_DETACH 2009-08-13 17:55:13.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-13 18:23:43.000000000 +0200 @@ -42,7 +42,6 @@ static const struct utrace_engine_ops pt static void ptrace_detach_task(struct task_struct *child, int sig) { - enum utrace_resume_action action = UTRACE_DETACH; struct utrace_engine *engine; int ret; @@ -51,19 +50,7 @@ static void ptrace_detach_task(struct ta if (unlikely(IS_ERR(engine))) return; - /* - * When leaving a parting signal to deliver, we cannot detach our - * utrace engine yet. We need it there to get a report_signal() - * callback that can inject our parting signal. Instead, we'll - * mark our engine by clearing its data pointer. Our callbacks - * will see this and know it's a PTRACE_DETACH still in progress. - */ - if (sig) { - engine->data = NULL; - action = UTRACE_INTERRUPT; - } - - ret = utrace_control(child, engine, action); + ret = utrace_control(child, engine, UTRACE_DETACH); WARN_ON(ret && ret != -EINPROGRESS && ret != -ESRCH && ret != -EALREADY); @@ -365,19 +352,6 @@ static u32 ptrace_resumed(struct task_st return UTRACE_SIGNAL_REPORT | ptrace_report_vfork_done(task); /* - * If PTRACE_DETACH had a signal for us to deliver, - * it didn't detach the engine, but marked it for us. - */ - if (!engine->data) { - read_lock(&tasklist_lock); - if (task->ptrace & PT_PTRACED) - engine->data = task->parent; - else - resume = UTRACE_DETACH; - read_unlock(&tasklist_lock); - } - - /* * If we're stopping, or we haven't reported any signal, * then we're all done for now. */ @@ -517,43 +491,18 @@ static struct utrace_engine *prepare_ptr struct task_struct *child, struct task_struct *parent) { struct utrace_engine *engine; -restart: + engine = utrace_attach_task(child, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, &ptrace_utrace_ops, parent); - if (engine == ERR_PTR(-EEXIST)) { - /* - * There is already some ptrace engine attached. Either - * this attach will fail because another ptracer is - * already attached, or else this engine was left behind - * by PTRACE_DETACH to deliver a signal. - */ - engine = utrace_attach_task(child, - UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); - if (IS_ERR(engine)) { - BUG_ON(PTR_ERR(engine) != -ENOENT); - goto restart; - } - if (engine->data) { - utrace_engine_put(engine); - engine = ERR_PTR(-EEXIST); - } - } + if (IS_ERR(engine)) { if (engine != ERR_PTR(-ESRCH) && engine != ERR_PTR(-ERESTARTNOINTR)) engine = ERR_PTR(-EPERM); } else { int ret = ptrace_update_utrace(child, engine); - if (ret == -EINPROGRESS) { - ret = utrace_barrier(child, engine); - utrace_engine_put(engine); - if (ret != -ERESTARTSYS) - goto restart; - return ERR_PTR(-ERESTARTNOINTR); - } if (ret) engine = ERR_PTR(finish_ptrace_attach(child, engine, -ESRCH)); From oleg at redhat.com Thu Aug 13 17:12:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 13 Aug 2009 19:12:26 +0200 Subject: [PATCH 06] do not use engine->data Message-ID: <20090813171226.GA29101@redhat.com> Do not use engine->data. It should point to struct ptrace_context (or, perhaps, struct utrace_ptrace ?) Indeed! now "make check" does not crash the kernel. Of course, I see a lot of FAIL's but not too much: 8. Upstream kernel reports 4/39 tests failed (under KVM). --- --- PU/kernel/ptrace.c~06_DONT_USE_DATA 2009-08-13 18:23:43.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-13 18:41:46.000000000 +0200 @@ -259,7 +259,7 @@ static u32 ptrace_report_clone(enum utra UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, &ptrace_utrace_ops, - parent->parent); + NULL); if (unlikely(IS_ERR(child_engine))) { WARN_ON(1); /* XXX */ } else { @@ -476,9 +476,8 @@ static int finish_ptrace_attach(struct t if (retval) { int error = utrace_control(task, engine, UTRACE_DETACH); WARN_ON(error && error != -ESRCH && error != -EALREADY); - } else { - engine->data = task->parent; } + utrace_engine_put(engine); return retval; } @@ -495,7 +494,7 @@ static struct utrace_engine *prepare_ptr engine = utrace_attach_task(child, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, parent); + &ptrace_utrace_ops, NULL); if (IS_ERR(engine)) { if (engine != ERR_PTR(-ESRCH) && From oleg at redhat.com Fri Aug 14 12:20:55 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 14 Aug 2009 14:20:55 +0200 Subject: [PATCH 0/3] utrace: SIGKILL tweaks Message-ID: <20090814122055.GA19638@redhat.com> Just to "complete" the previous discussion. Alternatively, we could just fix utrace_stop() to always check fatal_signal_pending() before return. But personally I think that report->killed buys nothing, but adds some complexity to the code. Perhaps, utrace_stop() should return true if we really stopped (like do_signal_stop() does). This looks more useful to me. But as always, up to you. I don't have a strong feeling. Oleg. From oleg at redhat.com Fri Aug 14 12:20:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 14 Aug 2009 14:20:58 +0200 Subject: [PATCH 1/3] finish_utrace_stop: use __fatal_signal_pending(), dont take ->siglock Message-ID: <20090814122058.GA19646@redhat.com> finish_utrace_stop() can check for pending SIGKILL lockless, ant it can use __fatal_signal_pending() helper. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) --- __UTRACE/kernel/utrace.c~1_FINISH_FATAL_SIGNAL 2009-08-14 11:58:05.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-14 12:43:44.000000000 +0200 @@ -354,17 +354,15 @@ static inline bool finish_utrace_stop(st * We're officially awake if it's clear. */ if (unlikely(utrace->stopped)) { - spin_lock(&utrace->lock); /* * If we're here with it still set, it must have been * signal_wake_up() instead, waking us up for a SIGKILL. */ - spin_lock_irq(&task->sighand->siglock); - WARN_ON(!sigismember(&task->pending.signal, SIGKILL)); - spin_unlock_irq(&task->sighand->siglock); + WARN_ON(!__fatal_signal_pending(task)); + spin_lock(&utrace->lock); utrace->stopped = 0; - killed = true; spin_unlock(&utrace->lock); + killed = true; } return killed; From oleg at redhat.com Fri Aug 14 12:21:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 14 Aug 2009 14:21:00 +0200 Subject: [PATCH 2/3] kill utrace_report->killed Message-ID: <20090814122100.GA19649@redhat.com> Kill utrace_report->killed and change the only user, utrace_get_signal(), to use fatal_signal_pending(). Similarly, change utrace_report_syscall_entry(), noe it is the only caller of utrace_stop() which checks the returned value. The boolean returned by utrace_stop()->finish_utrace_stop() is not very accurate. utrace_wakeup() can clear utrace->stopped but not wake up if SIGNAL_STOP_STOPPED. The tracee can sleep for a long time, then it can be SIGKILLED but in this case finish_utrace_stop() misses SIGKILL. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) --- __UTRACE/kernel/utrace.c~2_KILL_KILLED 2009-08-14 12:43:44.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-14 13:26:51.000000000 +0200 @@ -1262,12 +1262,12 @@ struct utrace_report { bool detaches; bool reports; bool takers; - bool killed; }; #define INIT_REPORT(var) \ - struct utrace_report var = { UTRACE_RESUME, 0, \ - false, false, false, false } + struct utrace_report var = { \ + .action = UTRACE_RESUME, \ + } /* * We are now making the report, so clear the flag saying we need one. @@ -1502,14 +1502,15 @@ bool utrace_report_syscall_entry(struct report.result | report.action, engine, current, regs); finish_report(&report, task, utrace); - if (report.action == UTRACE_STOP && - unlikely(utrace_stop(task, utrace, false))) + if (report.action == UTRACE_STOP) { + utrace_stop(task, utrace, false); /* * We are continuing despite UTRACE_STOP because of a * SIGKILL. Don't let the system call actually proceed. */ - return true; - + if (unlikely(fatal_signal_pending(task))) + return true; + } return report.result == UTRACE_SYSCALL_ABORT; } @@ -1707,7 +1708,7 @@ static void finish_resume_report(struct switch (report->action) { case UTRACE_STOP: - report->killed = utrace_stop(task, utrace, report->reports); + utrace_stop(task, utrace, report->reports); break; case UTRACE_INTERRUPT: @@ -2109,7 +2110,7 @@ int utrace_get_signal(struct task_struct */ finish_resume_report(&report, task, utrace); - if (unlikely(report.killed)) { + if (unlikely(fatal_signal_pending(task))) { /* * The only reason we woke up now was because of a * SIGKILL. Don't do normal dequeuing in case it From oleg at redhat.com Fri Aug 14 12:21:02 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 14 Aug 2009 14:21:02 +0200 Subject: [PATCH 3/3] change utrace_stop() to return void Message-ID: <20090814122102.GA19652@redhat.com> - Nobody uses the (inaccurate) value returned by utrace_stop(), change it to return void. - use fatal_signal_pending() instead of sigismember(SIGKILL). - finish_utrace_stop() becomes really trivial, it just clears ->stopped. Fold it into utrace_stop(). Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 57 ++++++++++++++++---------------------------------------- 1 file changed, 17 insertions(+), 40 deletions(-) --- __UTRACE/kernel/utrace.c~3_STOP_DONT_CK_KILLED 2009-08-14 13:26:51.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-14 13:54:54.000000000 +0200 @@ -341,44 +341,12 @@ static const struct utrace_engine_ops ut }; /* - * After waking up from TASK_TRACED, clear bookkeeping in @utrace. - * Returns true if we were woken up prematurely by SIGKILL. - */ -static inline bool finish_utrace_stop(struct task_struct *task, - struct utrace *utrace) -{ - bool killed = false; - - /* - * utrace_wakeup() clears @utrace->stopped before waking us up. - * We're officially awake if it's clear. - */ - if (unlikely(utrace->stopped)) { - /* - * If we're here with it still set, it must have been - * signal_wake_up() instead, waking us up for a SIGKILL. - */ - WARN_ON(!__fatal_signal_pending(task)); - spin_lock(&utrace->lock); - utrace->stopped = 0; - spin_unlock(&utrace->lock); - killed = true; - } - - return killed; -} - -/* * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. * @task == current, @utrace == current->utrace, which is not locked. - * Return true if we were woken up by SIGKILL even though some utrace - * engine may still want us to stay stopped. */ -static bool utrace_stop(struct task_struct *task, struct utrace *utrace, +static void utrace_stop(struct task_struct *task, struct utrace *utrace, bool report) { - bool killed; - /* * @utrace->stopped is the flag that says we are safely * inside this function. It should never be set on entry. @@ -393,10 +361,10 @@ static bool utrace_stop(struct task_stru spin_lock(&utrace->lock); spin_lock_irq(&task->sighand->siglock); - if (unlikely(sigismember(&task->pending.signal, SIGKILL))) { + if (unlikely(fatal_signal_pending(task))) { spin_unlock_irq(&task->sighand->siglock); spin_unlock(&utrace->lock); - return true; + return; } if (report) { @@ -429,9 +397,20 @@ static bool utrace_stop(struct task_stru * frozen that we freeze now before running anything substantial. */ try_to_freeze(); - - killed = finish_utrace_stop(task, utrace); - + /* + * utrace_wakeup() clears @utrace->stopped before waking us up. + * We're officially awake if it's clear. + */ + if (unlikely(utrace->stopped)) { + /* + * If we're here with it still set, it must have been + * signal_wake_up() instead, waking us up for a SIGKILL. + */ + WARN_ON(!__fatal_signal_pending(task)); + spin_lock(&utrace->lock); + utrace->stopped = 0; + spin_unlock(&utrace->lock); + } /* * While we were in TASK_TRACED, complete_signal() considered * us "uninterested" in signal wakeups. Now make sure our @@ -440,8 +419,6 @@ static bool utrace_stop(struct task_stru spin_lock_irq(&task->sighand->siglock); recalc_sigpending(); spin_unlock_irq(&task->sighand->siglock); - - return killed; } /* From bohcole at rediffmail.com Fri Aug 14 13:13:26 2009 From: bohcole at rediffmail.com (Bohman Cole) Date: Fri, 14 Aug 2009 09:13:26 -0400 Subject: A recommendation from a friend Message-ID: Good Day, We wish to notify you again that you were listed as a beneficiary to the total sum of 6,000,000.00 GBP (Six Million British Pounds) in the codicil and last testament of the deceased. (Name now withheld since this is our second letter to you). We contacted you because you bear the surname identity and therefore can present you as the beneficiary to the inheritance. We therefore reckoned that you could receive these funds as you are qualified by your name identity. All the legal papers will be processed upon your acceptance. Upon your acceptance of this deal, we request that you kindly forward to us your letter of acceptance, your current telephone and fax numbers and a forwarding address to enable us file necessary LEGAL documents in your name at our high court probate division for the release of the fund in question. Contact me immediately so that we can get this done. Kind regards, Mr.Bohman Cole --------- A user has sent this message from BarackObama.com. The sender's name, email address, subject and message have not been verified. -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Fri Aug 14 14:45:55 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 14 Aug 2009 16:45:55 +0200 Subject: [RFC, PATCH] teach utrace to destroy engine->data Message-ID: <20090814144555.GA28295@redhat.com> On 07/23, Oleg Nesterov wrote: > > On 07/22, Roland McGrath wrote: > > > > > Who will kfree() engine->data ? > > > > > > sys_ptrace(PTRACE_DETACH) can do this. But what if the tracer exits > > > and detaches? Or release_task() does untrace. > > > > All of these are some ptrace.c path that has to use UTRACE_DETACH, > ... > > Hmm. Yes, looks like you are right... Not sure what I was worried > about. I did have some concerns, but I guess I was wrong. Good! Now I recall why I was worried. And in fact, I think that without some change utrace->engine is hardly useable. Let's consider ptrace, but of course it is not special. We introduce struct ptrace_context {...} and change ptrace_attach() to setup engine->data to be a pointer to ptrace_context. Now. we should make sure that every user of UTRACE_DETACH frees engine->data. And, we have to introduce ptrace_report_reap() which should free it too. Note that this itself adds some complications. But the real problem is: the tracer can never safely dereference engine->data, the tracee can be killed/released at any moment. Sure. We can protect ->data by RCU, or add refcounting, etc. But this is nightmire. This is complex and (I bet) will lead to numerous bugs. I strongly believe that ->data should be freed by utrace_engine_put(). If you have the reference to engine, engine->data must be stable. So, this patch adds engine->dtor and utrace_engine_set_dtor() helper. It would be better to pass dtor as yet another argument to utrace_attach_task(). But this means more changes, and in this case it is better to have utrace_attach_create() and utrace_attach_lookup(), the new argument is only needed with UTRACE_ATTACH_CREATE. Afaics, unless a module intentionally leaks utrace_engine, it can safely use ->dtor() which lives in ->module_core. But at least it can always use ->dtor = kfree. Thoughts? Signed-off-by: Oleg Nesterov --- --- __UTRACE/include/linux/utrace.h~4_DTOR 2009-08-14 11:58:05.000000000 +0200 +++ __UTRACE/include/linux/utrace.h 2009-08-14 16:44:27.000000000 +0200 @@ -322,6 +322,7 @@ static inline enum utrace_syscall_action struct utrace_engine { /* private: */ struct kref kref; + void (*dtor)(void *data); struct list_head entry; /* public: */ @@ -342,6 +343,15 @@ static inline void utrace_engine_get(str kref_get(&engine->kref); } +/** + * utrace_engine_set_dtor - setup the destructor for ->data + */ +static inline void utrace_engine_set_dtor(struct utrace_engine *engine, + void (*dtor)(void *)) +{ + engine->dtor = dtor; +} + void __utrace_engine_release(struct kref *); /** @@ -349,7 +359,8 @@ void __utrace_engine_release(struct kref * @engine: &struct utrace_engine pointer * * You must hold a reference on @engine, and you lose that reference. - * If it was the last one, @engine becomes an invalid pointer. + * If it was the last one, @engine->dtor(@engine->data) is called and + * @engine becomes an invalid pointer. */ static inline void utrace_engine_put(struct utrace_engine *engine) { --- __UTRACE/kernel/utrace.c~4_DTOR 2009-08-14 13:54:54.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-14 16:29:37.000000000 +0200 @@ -79,6 +79,8 @@ void __utrace_engine_release(struct kref struct utrace_engine *engine = container_of(kref, struct utrace_engine, kref); BUG_ON(!list_empty(&engine->entry)); + if (engine->dtor) + engine->dtor(engine->data); kmem_cache_free(utrace_engine_cachep, engine); } EXPORT_SYMBOL_GPL(__utrace_engine_release); From roland at redhat.com Fri Aug 14 22:29:06 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 14 Aug 2009 15:29:06 -0700 (PDT) Subject: ptrace/utrace branch/tree? In-Reply-To: Ananth N Mavinakayanahalli's message of Wednesday, 12 August 2009 15:45:24 +0530 <20090812101524.GC4343@in.ibm.com> References: <20090812101524.GC4343@in.ibm.com> Message-ID: <20090814222906.26FAD40595@magilla.sf.frob.com> The changes that Oleg's sent for utrace proper I have been merging into my utrace git branch (and regenerating the patches that come from it). The ptrace rework includes some stages that do not depend on utrace. I previously collected some past drafts of Oleg's ptrace patches in: git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-roland.git branch ptrace/revamp Oleg may have newer versions of some of those, and I have not rebased that git tree to the upstream tip in a while now. Our plan has been to figure out a bit more of how things will shake out with the ptrace-over-utrace rewrite before we decide which cleanup patches are ready to submit upstream and in what order to do them. When Oleg thinks his current stuff is a little closer to ready, I'd like to have everything in a new git branch where we can juggle the sequence of patches to be sent upstream. As opposed to the existing utrace branch and its forks, which have local history, this would be a tree such that git-format-patch produces everything we'd post upstream. Then we can all review and test that sequence and sign off on posting it upstream. Thanks, Roland From roland at redhat.com Fri Aug 14 22:31:57 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 14 Aug 2009 15:31:57 -0700 (PDT) Subject: resume from another engine results in loss of singlestep req. In-Reply-To: Oleg Nesterov's message of Wednesday, 12 August 2009 14:32:51 +0200 <20090812123251.GA2039@redhat.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812072621.GB12098@linux.vnet.ibm.com> <20090812123251.GA2039@redhat.com> Message-ID: <20090814223157.2246C40595@magilla.sf.frob.com> > Btw. Roland, unless utrace_get_signal() does dequeue_signal(info), > we pass a random value in info->si_signo to ->report_signal(). > Yes, _if_ I understand correctly, report_signal can check action, > but perhaps it makes sense to set ->si_signo = 0, this may help to > engine writers. This is really another subject, and let's discuss that outside this thread about single-step. Please read the kerneldoc for @report_signal (utrace.h). > For example, probe5_a and probe5_b just blindly check ->si_signo. Srikar, also please read the kerneldoc for @report_signal (utrace.h). ;-) Thanks, Roland From roland at redhat.com Fri Aug 14 22:33:40 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 14 Aug 2009 15:33:40 -0700 (PDT) Subject: resume from another engine results in loss of singlestep req. In-Reply-To: Oleg Nesterov's message of Wednesday, 12 August 2009 17:56:24 +0200 <20090812155624.GA27975@redhat.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812072621.GB12098@linux.vnet.ibm.com> <20090812123251.GA2039@redhat.com> <20090812131843.GC12098@linux.vnet.ibm.com> <20090812155624.GA27975@redhat.com> Message-ID: <20090814223340.2FDBF40595@magilla.sf.frob.com> > Because you forgot to add QUIESCE to utrace_set_events's mask !!! D'oh! Perhaps it makes sense to have utrace_control() fail with -EINVAL or something when you try anything but RESUME or DETACH when you do not have UTRACE_EVENT(QUIESCE) set. Thanks, Roland From roland at redhat.com Fri Aug 14 23:07:28 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 14 Aug 2009 16:07:28 -0700 (PDT) Subject: resume from another engine results in loss of singlestep req. In-Reply-To: Oleg Nesterov's message of Wednesday, 12 August 2009 12:36:44 +0200 <20090812103644.GA29939@redhat.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812103644.GA29939@redhat.com> Message-ID: <20090814230728.F039840595@magilla.sf.frob.com> > Agreed, this looks like a right change to me. In any case I think this makes > the code more understandable and logical, and ->resume_action is much better > than ->reports imho. Ok. > But, you seem to forget to fix other callers of utrace_stop(), Yes, it was not a complete patch, just to get your feedback. I'll commit a more complete version. It's still not really right for the vfork case, but I want to avoid thinking about that for the moment. (I've always intended that eventually we would clean up the interaction with vfork-wait entirely differently.) > Can't we (well, partly) miss UTRACE_STOP request? > > Two engines A and B. Say, utrace_report_exec() calls ->report_exec(). > > A returns UTRACE_STOP, B returns UTRACE_INTERRUPT. > > ->resume_action = UTRACE_INTERRUPT, finish_report() sets ->interrupt = 1, > utrace_report_exec() returns. > > Now. We can't rely on utrace_resume()->finish_resume_report() which can > notice the stop request and do utrace_stop() to actually stop. This is > delayed until utrace_get_signal()->finish_resume_report(), and I am not > sure this is what we really want: > > - minor, but it is possible that tracehook_notify_jctl() will > be called before tracehook_get_signal(). Not a real problem, > but shouldn't UTRACE_STOP mean "stop as soon as possible" ? No. It means "stop before this thread can newly cause any userland-visible effects". That means before: * executing a syscall (i.e. after report_syscall_entry) * dequeuing a signal * returning to user mode If you used UTRACE_STOP and then get a report_jctl callback before stopping, that means there was a group stop that was not initiated by this thread. The completion of the group stop is a userland-visible effect, but that has already happened regardless, and was not caused by this thread. > - utrace_get_signal() can return without finish_resume_report() > if B->report_signal() (say) returns UTRACE_SIGNAL_DELIVER. > > Yes, in this case A->report_signal() can return UTRACE_STOP > again, this means utrace_get_signal() returns with ->report = T. That's how it's supposed to be. Everybody gets another look after the thread's state was changed by handler setup. > But another UTRACE_INTERRUPT can set ->interrupt, this can > "disable" ->report again, and so on. I don't follow. utrace_resume is guaranteed to be called. If UTRACE_INTERRUPT was used, then it punts because utrace_get_signal is guaranteed to be called as soon as it returns. Either way, everybody with UTRACE_EVENT(QUIESCE) set gets another callback. > In short: unless I missed something, it is hardly possible to predict when > the tracee will actually stop, perhaps UTRACE_STOP needs more respect? Sorry, I don't understand this comment at all. The tracee will actually stop before it would otherwise enter a syscall, dequeue a signal, or return to user mode. That is always the rule, end of story. I can't see what it is I am overlooking in the scenario that concerns you. Thanks, Roland From roland at redhat.com Fri Aug 14 23:25:01 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 14 Aug 2009 16:25:01 -0700 (PDT) Subject: resume from another engine results in loss of singlestep req. In-Reply-To: Oleg Nesterov's message of Wednesday, 12 August 2009 13:22:54 +0200 <20090812112254.GA32402@redhat.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812112254.GA32402@redhat.com> Message-ID: <20090814232501.E1AE540595@magilla.sf.frob.com> > Hmm. I think this is not exacly right. Suppose that > report->action == UTRACE_INTERRUPT but utrace->interrupt is already set. > In that case, since UTRACE_INTERRUPT <= UTRACE_REPORT, we set ->report. > > Not really bad, but not right anyway. Ah, true. It enables harmless but superfluous work. I've committed an equivalent change. Thanks, Roland From roland at redhat.com Fri Aug 14 23:56:17 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 14 Aug 2009 16:56:17 -0700 (PDT) Subject: [PATCH 0/3] utrace: SIGKILL tweaks In-Reply-To: Oleg Nesterov's message of Friday, 14 August 2009 14:20:55 +0200 <20090814122055.GA19638@redhat.com> References: <20090814122055.GA19638@redhat.com> Message-ID: <20090814235617.9253040595@magilla.sf.frob.com> > Alternatively, we could just fix utrace_stop() to always check > fatal_signal_pending() before return. I don't think it makes sense to roll in the check and have a return value for it unless either it's doing important synchronization there, or every caller needs the check. Oh, but it does retake the siglock before return. So it might as well roll it in and return the __fatal_signal_pending() result taken while it held the lock for recalc_sigpending(). But then you seem to think it can check it lockless. If that's kosher then can't these other checks use it lockless too (i.e. __fatal_signal_pending where you used fatal_signal_pending)? > But personally I think that report->killed buys nothing, but adds > some complexity to the code. If the siglock has to be taken at all, we should roll it into where utrace_stop takes it anyway for recalc_sigpending(). Then the return value, and even report.killed makes some sense, saving us this extra lock overhead. But if it's really OK to use __fatal_signal_pending() lockless in all the utrace.c places, then we can do it your way. > Perhaps, utrace_stop() should return true if we really stopped > (like do_signal_stop() does). This looks more useful to me. I don't see any purpose to such a return value for utrace_stop. Thanks, Roland From roland at redhat.com Sat Aug 15 00:20:29 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 14 Aug 2009 17:20:29 -0700 (PDT) Subject: [PATCH 2/3] kill utrace_report->killed In-Reply-To: Oleg Nesterov's message of Friday, 14 August 2009 14:21:00 +0200 <20090814122100.GA19649@redhat.com> References: <20090814122100.GA19649@redhat.com> Message-ID: <20090815002030.0548C40595@magilla.sf.frob.com> Oh, I misremembered the difference between fatal_signal_pending() and __fatal_signal_pending(), was thinking it had to do with siglock. I've merged all three patches now. Thanks, Roland From roland at redhat.com Sat Aug 15 01:37:27 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 14 Aug 2009 18:37:27 -0700 (PDT) Subject: [PATCH 00/6] utrace-ptrace: initial changes In-Reply-To: Oleg Nesterov's message of Thursday, 13 August 2009 19:12:12 +0200 <20090813171212.GA29074@redhat.com> References: <20090813171212.GA29074@redhat.com> Message-ID: <20090815013727.AAEE340595@magilla.sf.frob.com> I've merged those onto the utrace-ptrace branch. We can proceed however you'd like. But I'm not sure how much sense it makes to do it all by incremental change on the old utrace-ptrace branch. The way you're going, we'll have a new big utrace-ptrace.patch in the end. But I don't think that's what we'll need to submit upstream. In the end, what I expect we'll want is the ptrace-on-utrace work, and perhaps the utrace core itself too, split into smaller incremental pieces and intermingled with the non-utrace-dependent ptrace cleanup patches in whatever slices and order makes most sense for upstream review and merge. Thanks, Roland From oleg at redhat.com Mon Aug 17 15:19:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 17 Aug 2009 17:19:27 +0200 Subject: [PATCH 00/6] utrace-ptrace: initial changes In-Reply-To: <20090815013727.AAEE340595@magilla.sf.frob.com> References: <20090813171212.GA29074@redhat.com> <20090815013727.AAEE340595@magilla.sf.frob.com> Message-ID: <20090817151927.GA9581@redhat.com> On 08/14, Roland McGrath wrote: > > I've merged those onto the utrace-ptrace branch. We can proceed however > you'd like. But I'm not sure how much sense it makes to do it all by > incremental change on the old utrace-ptrace branch. The way you're going, > we'll have a new big utrace-ptrace.patch in the end. Yep. And I agree, this is not good. > But I don't think > that's what we'll need to submit upstream. > > In the end, what I expect we'll want is the ptrace-on-utrace work, and > perhaps the utrace core itself too, split into smaller incremental pieces The only problem, right now I can't imagine how to make the smaller incremental (and bisectable) changes. And more, I can't imagine how the code will look after rework. _Perhaps_, when the code will be ready, I will be able to split the changes. OK. As always, I did much less than expected. I am sending 07-09 trivial patches now. I need to think a bit before further changes. (I did a bit more change in fact, but then reverted them all and started from the beginning). Oleg. From oleg at redhat.com Mon Aug 17 15:22:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 17 Aug 2009 17:22:58 +0200 Subject: [PATCH 07] rework prepare_ptrace_attach/finish_ptrace_attach Message-ID: <20090817152258.GA10674@redhat.com> Introduce ptrace_attach_task() and ptrace_abort_attach(). There are simplified versions of prepare_ptrace_attach/finish_ptrace_attach and should be used instead. Change ptrace_attach() accordingly. This patch doesn't kill the old helpers and doesn't change ptrace_traceme() because I noticed it has another bug. Note the "XXX" comment in ptrace_abort_attach(). I am not sure a simple UTRACE_DETACH is always correct. We already did utrace_set_events(), we must not, say, lose a signal if it comes in between. --- kernel/ptrace.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) --- PU/kernel/ptrace.c~07_ATTACH 2009-08-13 18:41:46.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-17 15:31:07.000000000 +0200 @@ -509,6 +509,46 @@ static struct utrace_engine *prepare_ptr return engine; } +/* + * Attach a utrace engine for ptrace and set up its event mask. + * Returns error code or 0 on success. + */ +static int ptrace_attach_task(struct task_struct *tracee) +{ + struct utrace_engine *engine; + unsigned long events; + + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (unlikely(IS_ERR(engine))) { + int err = PTR_ERR(engine); + if (err != -ESRCH && err != -ERESTARTNOINTR) + err = -EPERM ; + return err; + } + /* + * We need QUIESCE for resume handling, CLONE to check + * for CLONE_PTRACE, other events are always reported. + */ + events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | + UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; + /* + * It can fail only if the tracee is dead, the caller + * must notice this before setting PT_PTRACED. + */ + utrace_set_events(tracee, engine, events); + utrace_engine_put(engine); + return 0; +} + +static void ptrace_abort_attach(struct task_struct *tracee) +{ + /* XXX we raced with detach. Double check UTRACE_DETACH is enough */ + ptrace_detach_task(tracee, 0); +} + int ptrace_check_attach(struct task_struct *child, int kill) { struct utrace_engine *engine; @@ -587,19 +627,14 @@ bool ptrace_may_access(struct task_struc int ptrace_attach(struct task_struct *task) { int retval; - struct utrace_engine *engine; audit_ptrace(task); retval = -EPERM; if (unlikely(task->flags & PF_KTHREAD)) - return retval; + goto out; if (same_thread_group(task, current)) - return retval; - - engine = prepare_ptrace_attach(task, current); - if (unlikely(IS_ERR(engine))) - return PTR_ERR(engine); + goto out; /* * Protect exec's credential calculations against our interference; @@ -616,6 +651,10 @@ int ptrace_attach(struct task_struct *ta if (retval) goto unlock_creds; + retval = ptrace_attach_task(task); + if (unlikely(retval)) + goto unlock_creds; + write_lock_irq(&tasklist_lock); retval = -EPERM; if (unlikely(task->exit_state)) @@ -633,10 +672,12 @@ int ptrace_attach(struct task_struct *ta retval = 0; unlock_tasklist: write_unlock_irq(&tasklist_lock); + if (retval) + ptrace_abort_attach(task); unlock_creds: mutex_unlock(&task->cred_guard_mutex); out: - return finish_ptrace_attach(task, engine, retval); + return retval; } /** From oleg at redhat.com Mon Aug 17 15:23:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 17 Aug 2009 17:23:00 +0200 Subject: [PATCH 08] change ptrace_traceme() to use the new helpers, kill prepare/finish attach Message-ID: <20090817152300.GA10678@redhat.com> Change ptrace_traceme() to use the new helpers. Kill the now unused prepare_ptrace_attach/finish_ptrace_attach. finish_ptrace_attach(ret) logic was wrong. If ->parent has PF_EXITING we must UTRACE_DETACH but ret == 0. Fix this. Note: we attach the new engine unconditionally, before security check. Not good, another task can do ptrace_attach() and get EPERM. Hopefully we can live with this race, or somehow fix it later. But security_ptrace_traceme() is strange anyway, I never understood it. It is called under tasklist_lock, but I can't see how this lock can help. ->parent can change its creds right after the check. Somehow with the last 2 patches the kernel survives after make xcheck. A lot of warning from ptrace_resumed()->WARN_ON(task->last_siginfo != info) but forget_original_parent()->BUG_ON(task_ptrace(p)) has gone away. I don't understand how this was "fixed", this means I missed something :/ I am ignoring ptrace_report_clone() for now. I think it should not rely on tracehook_finish_clone/tracehook_report_clone(). Instead it should do all work itself, we have PF_STARTING. In that case it can share the code with ptrace_traceme(). --- kernel/ptrace.c | 53 +++++------------------------------------------------ 1 file changed, 5 insertions(+), 48 deletions(-) --- PU/kernel/ptrace.c~08_TRACEME 2009-08-17 15:31:07.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-17 16:05:21.000000000 +0200 @@ -464,52 +464,6 @@ static const struct utrace_engine_ops pt }; /* - * Detach the utrace engine on error. On success, set @engine->data to - * the ptracer's task_struct pointer. This distinguishes an engine for - * attached ptrace from an engine left behind after a PTRACE_DETACH call - * that left a parting signal to deliver. - */ -static int finish_ptrace_attach(struct task_struct *task, - struct utrace_engine *engine, - int retval) -{ - if (retval) { - int error = utrace_control(task, engine, UTRACE_DETACH); - WARN_ON(error && error != -ESRCH && error != -EALREADY); - } - - utrace_engine_put(engine); - return retval; -} - -/* - * Attach a utrace engine for ptrace and set up its event mask. - * Returns the engine pointer or an IS_ERR() pointer. - */ -static struct utrace_engine *prepare_ptrace_attach( - struct task_struct *child, struct task_struct *parent) -{ - struct utrace_engine *engine; - - engine = utrace_attach_task(child, UTRACE_ATTACH_CREATE | - UTRACE_ATTACH_EXCLUSIVE | - UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); - - if (IS_ERR(engine)) { - if (engine != ERR_PTR(-ESRCH) && - engine != ERR_PTR(-ERESTARTNOINTR)) - engine = ERR_PTR(-EPERM); - } else { - int ret = ptrace_update_utrace(child, engine); - if (ret) - engine = ERR_PTR(finish_ptrace_attach(child, engine, - -ESRCH)); - } - return engine; -} - -/* * Attach a utrace engine for ptrace and set up its event mask. * Returns error code or 0 on success. */ @@ -688,13 +642,13 @@ out: */ int ptrace_traceme(void) { - int ret = -EPERM; - struct utrace_engine *engine; + bool detach = true; + int ret = ptrace_attach_task(current); - engine = prepare_ptrace_attach(current, current->parent); - if (unlikely(IS_ERR(engine))) - return PTR_ERR(engine); + if (unlikely(ret)) + return ret; + ret = -EPERM; write_lock_irq(&tasklist_lock); /* Are we already being traced? */ if (!current->ptrace) { @@ -707,11 +661,14 @@ int ptrace_traceme(void) if (!ret && !(current->real_parent->flags & PF_EXITING)) { current->ptrace = PT_PTRACED; __ptrace_link(current, current->real_parent); + detach = false; } } write_unlock_irq(&tasklist_lock); - return finish_ptrace_attach(current, engine, ret); + if (detach) + ptrace_abort_attach(current); + return ret; } /* From oleg at redhat.com Mon Aug 17 15:23:02 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 17 Aug 2009 17:23:02 +0200 Subject: [PATCH 09] introduce the empty struct ptrace_context Message-ID: <20090817152302.GA10685@redhat.com> Introduce the empty struct ptrace_context, change ptrace_attach_task() to setup engine->data. It should be used for ptrace_set_action() and ptrace_set_stop_event(), the current usage of ->ptrace is racy. Also, ->exit_code and ->last_siginfo should live in engine->data too. Eventually, all ptrace-related members should be moved from task_struct. Note! with this patch every attach means the memory leak, we never free engine->data. I am not sure how we should free, let's discuss "[RFC, PATCH] teach utrace to destroy engine->data" first. --- kernel/ptrace.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~09_CONTEXT 2009-08-17 16:05:21.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-17 16:25:12.000000000 +0200 @@ -24,6 +24,8 @@ #include #include +struct ptrace_context { +}; /* * ptrace a task: make the debugger its new parent and @@ -469,17 +471,23 @@ static const struct utrace_engine_ops pt */ static int ptrace_attach_task(struct task_struct *tracee) { + struct ptrace_context *context; struct utrace_engine *engine; unsigned long events; + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (unlikely(!context)) + return -ENOMEM; + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); + &ptrace_utrace_ops, context); if (unlikely(IS_ERR(engine))) { int err = PTR_ERR(engine); if (err != -ESRCH && err != -ERESTARTNOINTR) - err = -EPERM ; + err = -EPERM; + kfree(context); return err; } /* From oleg at redhat.com Mon Aug 17 15:31:23 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 17 Aug 2009 17:31:23 +0200 Subject: resume from another engine results in loss of singlestep req. In-Reply-To: <20090814230728.F039840595@magilla.sf.frob.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812103644.GA29939@redhat.com> <20090814230728.F039840595@magilla.sf.frob.com> Message-ID: <20090817153123.GA10727@redhat.com> On 08/14, Roland McGrath wrote: > > > - minor, but it is possible that tracehook_notify_jctl() will > > be called before tracehook_get_signal(). Not a real problem, > > but shouldn't UTRACE_STOP mean "stop as soon as possible" ? > > No. It means "stop before this thread can newly cause any userland-visible > effects". That means before: > > * executing a syscall (i.e. after report_syscall_entry) > * dequeuing a signal > * returning to user mode OK, > > - utrace_get_signal() can return without finish_resume_report() > > if B->report_signal() (say) returns UTRACE_SIGNAL_DELIVER. > > > > Yes, in this case A->report_signal() can return UTRACE_STOP > > again, this means utrace_get_signal() returns with ->report = T. > > That's how it's supposed to be. Everybody gets another look after the > thread's state was changed by handler setup. > > > But another UTRACE_INTERRUPT can set ->interrupt, this can > > "disable" ->report again, and so on. > > I don't follow. utrace_resume is guaranteed to be called. Well, utrace_resume() will be called, yes. But it does nothing when ->interrupt == T. But this doesn't matter. Your clarification above answers my question. Oleg. From mldireto at tudoemoferta.com.br Mon Aug 17 20:39:00 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Mon, 17 Aug 2009 17:39:00 -0300 Subject: Ainda da tempo de ganhar a sua bicicleta da Sundown. Message-ID: <5ca394cc98d6d22ab9020afb0016b1e1@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From roland at redhat.com Tue Aug 18 00:04:22 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 17:04:22 -0700 (PDT) Subject: [PATCH 00/6] utrace-ptrace: initial changes In-Reply-To: Oleg Nesterov's message of Monday, 17 August 2009 17:19:27 +0200 <20090817151927.GA9581@redhat.com> References: <20090813171212.GA29074@redhat.com> <20090815013727.AAEE340595@magilla.sf.frob.com> <20090817151927.GA9581@redhat.com> Message-ID: <20090818000422.AD8174730F@magilla.sf.frob.com> > The only problem, right now I can't imagine how to make the smaller > incremental (and bisectable) changes. > > And more, I can't imagine how the code will look after rework. _Perhaps_, > when the code will be ready, I will be able to split the changes. Right. I'm sure it will be easier to figure out an incremental path once we are much more sure about what the end-state looks like. I think it makes the most sense to concentrate now only on what seems most efficient at making progress. If it muddies things for you to worry about the incremental changes, then don't worry about it yet. Thanks, Roland From roland at redhat.com Tue Aug 18 00:07:09 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 17:07:09 -0700 (PDT) Subject: [PATCH 07] rework prepare_ptrace_attach/finish_ptrace_attach In-Reply-To: Oleg Nesterov's message of Monday, 17 August 2009 17:22:58 +0200 <20090817152258.GA10674@redhat.com> References: <20090817152258.GA10674@redhat.com> Message-ID: <20090818000709.CD9F04730F@magilla.sf.frob.com> > + /* > + * It can fail only if the tracee is dead, the caller > + * must notice this before setting PT_PTRACED. > + */ > + utrace_set_events(tracee, engine, events); I'd say put at least a WARN_ON(ret) there if you are really assuming success. Thanks, Roland From roland at redhat.com Tue Aug 18 00:15:22 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 17:15:22 -0700 (PDT) Subject: [PATCH 07] rework prepare_ptrace_attach/finish_ptrace_attach In-Reply-To: Oleg Nesterov's message of Monday, 17 August 2009 17:22:58 +0200 <20090817152258.GA10674@redhat.com> References: <20090817152258.GA10674@redhat.com> Message-ID: <20090818001522.206234730F@magilla.sf.frob.com> Forgot to answer this in the first reply, sorry. > Note the "XXX" comment in ptrace_abort_attach(). I am not sure a simple > UTRACE_DETACH is always correct. We already did utrace_set_events(), we > must not, say, lose a signal if it comes in between. I don't follow what scenario you are concerned with here. UTRACE_DETACH will never cause you to "lose" anything. Either you'll get some callback you've enabled before the detach completes (before your utrace_control call, or after or simultaneous with a -EINPROGRESS return from it), or you won't. If you don't, the signal does its normal thing. If you do, you do. The callback just needs to: return utrace_signal_action(action) | UTRACE_DETACH; or return utrace_signal_action(action) | UTRACE_RESUME; to have no effect on the signal. Thanks, Roland From roland at redhat.com Tue Aug 18 00:31:30 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 17:31:30 -0700 (PDT) Subject: [PATCH 08] change ptrace_traceme() to use the new helpers, kill prepare/finish attach In-Reply-To: Oleg Nesterov's message of Monday, 17 August 2009 17:23:00 +0200 <20090817152300.GA10678@redhat.com> References: <20090817152300.GA10678@redhat.com> Message-ID: <20090818003130.5439F4730F@magilla.sf.frob.com> > Note: we attach the new engine unconditionally, before security check. > Not good, another task can do ptrace_attach() and get EPERM. Hopefully > we can live with this race, or somehow fix it later. I don't think we can accept that and call it non-regressing. But we can worry about it later. > But security_ptrace_traceme() is strange anyway, I never understood it. > It is called under tasklist_lock, but I can't see how this lock can > help. ->parent can change its creds right after the check. It may well just be that the LSM check was originally inserted in a place where tasklist_lock was held for incidental reasons. You should check with the security folks about what really matters for that. > Somehow with the last 2 patches the kernel survives after make xcheck. :-) I bet we can still break it. > A lot of warning from ptrace_resumed()->WARN_ON(task->last_siginfo != info) That was around for a long time and I never figured it out. But it almost certainly indicates some misbehavior would occur in some usage patterns, even if not ones we have figured out specifically how to test. > I am ignoring ptrace_report_clone() for now. I think it should not > rely on tracehook_finish_clone/tracehook_report_clone(). Instead it > should do all work itself, we have PF_STARTING. Right. This was the main reason (only reason, really) for the special UTRACE_ATTACH_CREATE ordering guarantee that necessitates PF_STARTING. (If it helps, we can also reconsider how that logic is specified in the utrace API and/or how we implement it.) In fact, it's the main reason for being able to use UTRACE_ATTACH_MATCH_OPS|UTRACE_ATTACH_EXCLUSIVE at all. > In that case it can share the code with ptrace_traceme(). I'm not sure I quite follow that. Both PTRACE_TRACEME and PTRACE_ATTACH paths have to interlock with each other. Auto-tracing in report_clone doesn't have to worry about that at all, because of the special priority report_clone gets for UTRACE_ATTACH_CREATE. It's more like PTRACE_ATTACH in that it runs in the parent context (inside clone/fork), whereas PTRACE_TRACEME may have fewer issues to worry about because it runs in the tracee context. Thanks, Roland From roland at redhat.com Tue Aug 18 00:47:54 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 17:47:54 -0700 (PDT) Subject: [PATCH 09] introduce the empty struct ptrace_context In-Reply-To: Oleg Nesterov's message of Monday, 17 August 2009 17:23:02 +0200 <20090817152302.GA10685@redhat.com> References: <20090817152302.GA10685@redhat.com> Message-ID: <20090818004754.7A3204730F@magilla.sf.frob.com> Does this mean you intend to abandon the ptrace-revamp draft series that added ptrace_context et al cleanups in the pre-utrace code? Or are you culling bits from there to integrate differently now? > It should be used for ptrace_set_action() and ptrace_set_stop_event(), > the current usage of ->ptrace is racy. Indeed. > Also, ->exit_code and ->last_siginfo should live in engine->data too. Well, task_struct.exit_code has core non-ptrace uses, i.e. wait. What you mean is stop overloading it for ptrace wait status and resumption signal, and use appropriate explicit bookkeeping for that ptrace_context. > Eventually, all ptrace-related members should be moved from task_struct. Yay! (ptrace-tracee-related, you mean. The ptrace-tracer-related ones of course still have to live somewhere hung off task_struct, though they sorely need cleanup as we know.) > Note! with this patch every attach means the memory leak, we never > free engine->data. I am not sure how we should free, let's discuss > "[RFC, PATCH] teach utrace to destroy engine->data" first. Ok. Then I'm not going to merge this one for the moment. I'll follow up on that thread shortly. I'm sorry I did not get to it before today. Thanks, Roland From roland at redhat.com Tue Aug 18 00:57:39 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 17:57:39 -0700 (PDT) Subject: [PATCH 07] rework prepare_ptrace_attach/finish_ptrace_attach In-Reply-To: Oleg Nesterov's message of Monday, 17 August 2009 17:22:58 +0200 <20090817152258.GA10674@redhat.com> References: <20090817152258.GA10674@redhat.com> Message-ID: <20090818005739.BB5854730F@magilla.sf.frob.com> I merged 7 and 8. My review comments on these are just to raise things to think about between now and the final form. I don't intend them to slow down the progress of your current hacking. Thanks, Roland From roland at redhat.com Tue Aug 18 00:58:24 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 17:58:24 -0700 (PDT) Subject: resume from another engine results in loss of singlestep req. In-Reply-To: Oleg Nesterov's message of Monday, 17 August 2009 17:31:23 +0200 <20090817153123.GA10727@redhat.com> References: <20090811145211.GA30132@linux.vnet.ibm.com> <20090811172310.GA14672@redhat.com> <20090811213739.EA81A4259E@magilla.sf.frob.com> <20090812103644.GA29939@redhat.com> <20090814230728.F039840595@magilla.sf.frob.com> <20090817153123.GA10727@redhat.com> Message-ID: <20090818005824.9E94D4730F@magilla.sf.frob.com> > Well, utrace_resume() will be called, yes. But it does nothing when > ->interrupt == T. Right. > But this doesn't matter. Your clarification above answers my question. Ok, good. Thanks, Roland From roland at redhat.com Tue Aug 18 02:33:07 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 19:33:07 -0700 (PDT) Subject: [PATCH] utrace_control: return -EINVAL for missing UTRACE_EVENT(QUIESCE) Message-ID: <20090818023307.F0A954730F@magilla.sf.frob.com> In-Reply-To: Oleg Nesterov's message of Monday, 17 August 2009 17:31:23 +0200 <20090817153123.GA10727 at redhat.com> References: <20090811145211.GA30132 at linux.vnet.ibm.com> <20090811172310.GA14672 at redhat.com> <20090811213739.EA81A4259E at magilla.sf.frob.com> <20090812103644.GA29939 at redhat.com> <20090814230728.F039840595 at magilla.sf.frob.com> <20090817153123.GA10727 at redhat.com> X-Shopping-List: (1) Vehement aggressors (2) Asiatic Pencil bruisers (3) Insufficient attention (4) Decadent animals I've added this patch to help module-writers diagnose problems like the one that came up recently more quickly. This especially helps for these cases where things can very well work fine without supplying a callback in simple tests, but then fail later when circumstances are more complicated (like unrelated other engines being around). Note I did not make it check event bits for UTRACE_STOP or UTRACE_INTERRUPT. While it's usual practice to use these in concern with a report_quiesce callback as with UTRACE_REPORT et al, there are meaningful ways to use these without callbacks. Signed-off-by: Roland McGrath --- kernel/utrace.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/kernel/utrace.c b/kernel/utrace.c index fa2a719..35be909 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -985,6 +985,9 @@ static inline int utrace_control_dead(struct task_struct *target, * stopped, then there might be no callbacks until all engines let * it resume. * + * Since this is meaningless unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * * UTRACE_INTERRUPT: * * This is like %UTRACE_REPORT, but ensures that @target will make a @@ -1013,12 +1016,18 @@ static inline int utrace_control_dead(struct task_struct *target, * @report_quiesce callback with a zero event mask, or the * @report_signal callback with %UTRACE_SIGNAL_REPORT. * + * Since this is not robust unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * * UTRACE_BLOCKSTEP: * * It's invalid to use this unless arch_has_block_step() returned true. * This is like %UTRACE_SINGLESTEP, but resumes for one whole basic * block of user instructions. * + * Since this is not robust unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * * %UTRACE_BLOCKSTEP devolves to %UTRACE_SINGLESTEP when another * tracing engine is using %UTRACE_SINGLESTEP at the same time. */ @@ -1033,6 +1042,18 @@ int utrace_control(struct task_struct *target, if (unlikely(action > UTRACE_DETACH)) return -EINVAL; + /* + * This is a sanity check for a programming error in the caller. + * Their request can only work properly in all cases by relying on + * a follow-up callback, but they didn't set one up! This check + * doesn't do locking, but it shouldn't matter. The caller has to + * be synchronously sure the callback is set up to be operating the + * interface properly. + */ + if (action >= UTRACE_REPORT && action < UTRACE_RESUME && + unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) + return -EINVAL; + utrace = get_utrace_lock(target, engine, true); if (unlikely(IS_ERR(utrace))) return PTR_ERR(utrace); From roland at redhat.com Tue Aug 18 04:54:33 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 21:54:33 -0700 (PDT) Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: Oleg Nesterov's message of Friday, 14 August 2009 16:45:55 +0200 <20090814144555.GA28295@redhat.com> References: <20090814144555.GA28295@redhat.com> Message-ID: <20090818045433.511254730F@magilla.sf.frob.com> > Now. we should make sure that every user of UTRACE_DETACH frees > engine->data. And, we have to introduce ptrace_report_reap() which > should free it too. Right, or you can have a report_death callback (or even just report_quiesce when passed UTRACE_EVENT(DEATH)) that always detaches. In that event you don't really need report_reap. (In theory, this is how ptrace would be. It doesn't have any use for utrace once a task has died. But in practice it depends entirely on how the wait interference is done--that is outside of utrace proper, but you could conceivably want to use report_reap as the mechanism for synchronizing with de_thread(), which is the one place that ordinarily preempts the ptrace wait interference.) > Note that this itself adds some complications. But the real problem > is: the tracer can never safely dereference engine->data, the tracee > can be killed/released at any moment. I see two basic models for handling the engine lifetime issues in a utrace engine. One way is where you do not normally hold a utrace_engine reference. You get an initial one from UTRACE_ATTACH_CREATE when you do setup. Once you have done utrace_set_events() and maybe utrace_control(), you do utrace_engine_put() immediately. Then if you have callbacks that use UTRACE_DETACH (or else have report_reap, where it's implicit) they are responsible for engine->data. And indeed you must have some such if you have an engine->data pointer that needs cleanup. This model is probably a good fit for "passive" tracing, where the only thing you really come back and do later is disable it (or for something simple enough it doesn't need any cleanup for engine->data). Then you can do: engine = utrace_attach_task(task, UTRACE_ATTACH_MATCH_OPS, &my_ops, NULL); if (IS_ERR(engine)) ... ret = utrace_control(task, engine, UTRACE_DETACH); if (ret) ... clean_up(engine->data); where -ESRCH/-EALREADY tell you that your report_reap/report_death (also counts for report_quiesce in the report_death pass) either will run, has run, or is running, so in that case you rely on them to do: clean_up(engine->data); return UTRACE_DETACH; The logic is the same for "disable" rather than "detach", using utrace_set_events(task, engine, 0) rather than utrace_control(). The same return values tell you if there is a death race. In either case, you'd follow up with utrace_barrier() for -EINPROGRESS unless the only kind of race that's of concern for your case is a death race (such as when you're sure it was stopped in a place where you could get no other callbacks, or you don't have other callbacks anyway). The second model is where you normally hold a utrace_engine reference to represent the life of your data structure, separate from the implicit utrace_engine reference for being attached. The engine uses the rule that the code that drops the last engine reference cleans up the data structure, rather than the code that detaches doing that. You might have whatever callbacks that decide to use UTRACE_DETACH if that's appropriate. But these would not necessarily free your data structures. Instead, the control path does that well after detach, when it does the final utrace_engine_put(). This model seems like a better fit for ptrace to me. The anchoring data structure is the tracer's tracees list, which links together the ptrace_context structs. A live ptrace_context has an engine pointer and a ref for it. When a tracee dies, it uses UTRACE_DETACH and so drops the implicit engine ref, leaving only the ptrace_context's ref. The tracer cleans this all up when it fake-reaps the zombie in wait. There is whatever non-utrace magic to turn off the wait interference, and also the de_thread() race vs wait interference. But those really are special to ptrace. For de_thread() you could do something hairy with report_reap, or you could just handle it lazily with a task ref and EXIT_DEAD checks to clean up and ignore it in the next wait. (So all the MT exec zombies will be released but not __put_task_struct until the debugger waits after the PTRACE_EVENT_EXEC/SIGTRAP stop. Or you could even make the debugger see all the "zombies" that MT-exec now robs it of, since their ->exit_code is all it was really going to get anyway and you can still see it just as well in EXIT_DEAD. I guess that's not really any good as a feature if the pid could be reused.) In the general case, I would expect asynchronous controllers to be going from their own data structures to utrace_engine + task_struct/struct pid rather than the other way around. But you can still use a utrace_attach lookup if you like. (It seems handy because it's behind an API, but you're really just choosing O(n) in the number of unrelated engines on that task vs O(n) in the number of tracees walking your own data structure. That's probably the right choice for ptrace, but you always have lots of choices.) Just don't use attachedness to govern the life of your data structure--that's what gives you trouble. It's true that utrace_attach lookups won't work when the engine is no longer attached, but it also so happens that ptrace() wants to fail with ESRCH whenever called for a dead or otherwise detached task anyway. In general, and perhaps for ptrace, I'd expect a utrace module to have some locking regime governing a list of tracees, and use that to control removing and deallocating elements from that list. If it wants to have some of its utrace callbacks decide to both detach and remove an element from a list, then that code would obey that locking regime to touch the list before deallocating and returning UTRACE_DETACH. > Sure. We can protect ->data by RCU, or add refcounting, etc. But > this is nightmire. This is complex and (I bet) will lead to numerous > bugs. There are lots of ways to go about it. Part of the point of utrace is not to tie you down to a particular plan for that. Fancy users can do RCU and so forth to be really well-optimized, and we don't want to add anything to the reporting hot paths where savvy utrace modules can't optimize it out. But I'm always open to adding things to make it easier to write modules (and with fewer bugs), when it doesn't constrain the best that sophosticated uses can do and doesn't overcomplicate the API in general. > I strongly believe that ->data should be freed by utrace_engine_put(). > If you have the reference to engine, engine->data must be stable. Well, that's a rule you can decide you want for your engine's handling of its ->data, sure. You can in fact do that already, since you really are in control of all the gets and puts. There is one put that's implicit in detach, but you always either choose to detach or at least could be notified. All other gets and puts are what your engine's code chose to do. > So, this patch adds engine->dtor and utrace_engine_set_dtor() helper. The proper interface for this is just to add .release to utrace_engine_ops. Because of how we fiddle the fields in detach, we'd still need to put the function pointer into struct utrace_engine at some point in the implementation. But the API doesn't really need to know about that. I would prefer to find a way to implement it without adding another word to struct utrace_engine. But it's probably not worth the effort. Perhaps one day we'll rethink the reporting races and find a way to handle detach without changing ->ops (rely on list_empty() or something). But we can worry about that much later, if at all. > Afaics, unless a module intentionally leaks utrace_engine, it can safely > use ->dtor() which lives in ->module_core. But at least it can always > use ->dtor = kfree. I've never really figured out all the issues about module unloading for utrace. I assume that's what you're referring to here. The two obvious safe paths would seem to be either holding module refs whenever an engine is attached (or now, until your release hook is called), or synchronously detaching all engines (plus utrace_barrier et al) in the module_exit function. Thanks, Roland From roland at redhat.com Tue Aug 18 05:10:49 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 Aug 2009 22:10:49 -0700 (PDT) Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: Oleg Nesterov's message of Friday, 14 August 2009 16:45:55 +0200 <20090814144555.GA28295@redhat.com> References: <20090814144555.GA28295@redhat.com> Message-ID: <20090818051049.A9E9C4730F@magilla.sf.frob.com> If we do add the destructor hook, I think it looks like this. It would merit some write-up in utrace.tmpl text too. I'm not especially convinced it's a very good idea. But I won't object if people serious about using the API think it helps. Thanks, Roland --- include/linux/utrace.h | 8 ++++++++ kernel/utrace.c | 3 +++ 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/include/linux/utrace.h b/include/linux/utrace.h index c19c01b..f968792 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h @@ -322,6 +322,7 @@ static inline enum utrace_syscall_action utrace_syscall_action(u32 action) struct utrace_engine { /* private: */ struct kref kref; + void (*release)(void *); struct list_head entry; /* public: */ @@ -539,6 +540,12 @@ static inline void utrace_engine_put(struct utrace_engine *engine) * Unlike other callbacks, this can be called from the parent's context * rather than from the traced thread itself--it must not delay the * parent by blocking. + * + * @release: + * If not %NULL, this is called after the last utrace_engine_put() + * call for a &struct utrace_engine, which could be implicit after + * a %UTRACE_DETACH return from another callback. Its argument is + * the engine's @data member. */ struct utrace_engine_ops { u32 (*report_quiesce)(enum utrace_resume_action action, @@ -584,6 +591,7 @@ struct utrace_engine_ops { bool group_dead, int signal); void (*report_reap)(struct utrace_engine *engine, struct task_struct *task); + void (*release)(void *data); }; /** diff --git a/kernel/utrace.c b/kernel/utrace.c index 35be909..3b7ac74 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -79,6 +79,8 @@ void __utrace_engine_release(struct kref *kref) struct utrace_engine *engine = container_of(kref, struct utrace_engine, kref); BUG_ON(!list_empty(&engine->entry)); + if (engine->release) + (*engine->release)(engine->data); kmem_cache_free(utrace_engine_cachep, engine); } EXPORT_SYMBOL_GPL(__utrace_engine_release); @@ -271,6 +273,7 @@ struct utrace_engine *utrace_attach_task( engine->flags = 0; engine->ops = ops; engine->data = data; + engine->release = ops->release; ret = utrace_attach_delay(target); if (likely(!ret)) From oleg at redhat.com Tue Aug 18 14:34:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 18 Aug 2009 16:34:53 +0200 Subject: [PATCH] utrace_control: return -EINVAL for missing UTRACE_EVENT(QUIESCE) In-Reply-To: <20090818023307.F0A954730F@magilla.sf.frob.com> References: <20090818023307.F0A954730F@magilla.sf.frob.com> Message-ID: <20090818143453.GA7522@redhat.com> On 08/17, Roland McGrath wrote: > > @@ -1033,6 +1042,18 @@ int utrace_control(struct task_struct *target, > if (unlikely(action > UTRACE_DETACH)) > return -EINVAL; > > + /* > + * This is a sanity check for a programming error in the caller. > + * Their request can only work properly in all cases by relying on > + * a follow-up callback, but they didn't set one up! This check > + * doesn't do locking, but it shouldn't matter. The caller has to > + * be synchronously sure the callback is set up to be operating the > + * interface properly. > + */ > + if (action >= UTRACE_REPORT && action < UTRACE_RESUME && > + unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) > + return -EINVAL; Agreed, this can help to catch the problems. Unfortunately, this doesn't help if a module doesn't use utrace_control() but just returns UTRACE_SINGLESTEP/etc. Like Srikar's test-case does. But I guess we can do nothing in this case, except perhaps we could add pr_debug() into finish_callback(). I dunno. And in any case, the warning from finish_callback() can't be always correct. Oleg. From oleg at redhat.com Tue Aug 18 14:36:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 18 Aug 2009 16:36:41 +0200 Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: <20090818051049.A9E9C4730F@magilla.sf.frob.com> References: <20090814144555.GA28295@redhat.com> <20090818051049.A9E9C4730F@magilla.sf.frob.com> Message-ID: <20090818143641.GB7522@redhat.com> On 08/17, Roland McGrath wrote: > > If we do add the destructor hook, I think it looks like this. > ... > @@ -271,6 +273,7 @@ struct utrace_engine *utrace_attach_task( > engine->flags = 0; > engine->ops = ops; > engine->data = data; > + engine->release = ops->release; Agreed! this is much better. Oleg. From oleg at redhat.com Tue Aug 18 15:00:18 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 18 Aug 2009 17:00:18 +0200 Subject: [PATCH 09] introduce the empty struct ptrace_context In-Reply-To: <20090818004754.7A3204730F@magilla.sf.frob.com> References: <20090817152302.GA10685@redhat.com> <20090818004754.7A3204730F@magilla.sf.frob.com> Message-ID: <20090818150018.GC7522@redhat.com> On 08/17, Roland McGrath wrote: > > Does this mean you intend to abandon the ptrace-revamp draft series that > added ptrace_context et al cleanups in the pre-utrace code? Well, yes. I don't think this series makes sense before utrace-ptrace. Firstly, it adds task_struct->ptrace_ctx (and kzalloc to tracehooks + kfree to free_task) which utrace-ptrace does not need. Giwen that we are going to forget about the old ptrace code, this just means more necessary changes. And. At least ->parent and ->ptrace_entry need more attention with utrace-ptrace, it is not easy to migrate them right now. This again means this draft series adds more problems. > Or are you > culling bits from there to integrate differently now? Yes, I hope. At least partly. > > Also, ->exit_code and ->last_siginfo should live in engine->data too. > > Well, task_struct.exit_code has core non-ptrace uses, i.e. wait. What you > mean is stop overloading it for ptrace wait status and resumption signal, > and use appropriate explicit bookkeeping for that ptrace_context. Yes, exactly. Oleg. From oleg at redhat.com Tue Aug 18 15:17:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 18 Aug 2009 17:17:24 +0200 Subject: [PATCH 08] change ptrace_traceme() to use the new helpers, kill prepare/finish attach In-Reply-To: <20090818003130.5439F4730F@magilla.sf.frob.com> References: <20090817152300.GA10678@redhat.com> <20090818003130.5439F4730F@magilla.sf.frob.com> Message-ID: <20090818151724.GD7522@redhat.com> On 08/17, Roland McGrath wrote: > > > In that case it can share the code with ptrace_traceme(). > > I'm not sure I quite follow that. Both PTRACE_TRACEME and PTRACE_ATTACH > paths have to interlock with each other. Auto-tracing in report_clone > doesn't have to worry about that at all, because of the special priority > report_clone gets for UTRACE_ATTACH_CREATE. It's more like PTRACE_ATTACH > in that it runs in the parent context (inside clone/fork), Yes. But we attach to parent->parent, not to parent == current. It runs in context of ptraced task, and the ptracer/context is not "stable". The tracer can exit and detach. We should be careful, like in PTRACE_TRACEME case. In short: ptrace_report_clone() should "copy" the tracing state from current to child when needed. And it should never attach if current is not traced. In particular, this means that if (event || (clone_flags & CLONE_PTRACE)) { child_engine = utrace_attach_task(child, UTRACE_ATTACH_CREATE ... is not right. CLONE_PTRACE should be ignored unless task_ptrace(current). > whereas > PTRACE_TRACEME may have fewer issues to worry about because it runs in > the tracee context. Yes, but otoh, the freshly forked task can't run at all, we didn't call wake_up_new_task() yet. This means, we have fewer issues to worry, like if it was current. I think we will see what makes more sense. Oleg. From oleg at redhat.com Tue Aug 18 16:44:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 18 Aug 2009 18:44:00 +0200 Subject: [PATCH 07] rework prepare_ptrace_attach/finish_ptrace_attach In-Reply-To: <20090818001522.206234730F@magilla.sf.frob.com> References: <20090817152258.GA10674@redhat.com> <20090818001522.206234730F@magilla.sf.frob.com> Message-ID: <20090818164400.GA13635@redhat.com> On 08/17, Roland McGrath wrote: > > > Note the "XXX" comment in ptrace_abort_attach(). I am not sure a simple > > UTRACE_DETACH is always correct. We already did utrace_set_events(), we > > must not, say, lose a signal if it comes in between. > > I don't follow what scenario you are concerned with here. Note that I don't really understand why I am worried ;) This "XXX" is just a temporary marker, to remind that perhaps we should be careful with the future changes. But please see below. > UTRACE_DETACH will never cause you to "lose" anything. Either you'll get > some callback you've enabled before the detach completes (before your > utrace_control call, or after or simultaneous with a -EINPROGRESS return > from it), or you won't. If you don't, the signal does its normal thing. > If you do, you do. The callback just needs to: > return utrace_signal_action(action) | UTRACE_DETACH; > or > return utrace_signal_action(action) | UTRACE_RESUME; > to have no effect on the signal. Suppose we have a ptraced task C, it is ->stopped. C->parent calls ptrace_detach(0), utrace_control(UTRACE_DETACH), but doesn't clear ->ptrace yet. UTRACE_DETACH wakes up the tracee. (Or, C can be running, ptracer exits and detaches). A new tracer P calls ptrace_attach(C), installs the new engine E, and calls utrace_set_events(... | UTRACE_EVENT_SIGNAL_ALL). C recieves a signal, notices task_utrace_flags(), calls utrace_get_signal(), dequeues the signal, calls E->ops->ptrace_report_signal() which returns UTRACE_STOP. C does finish_resume_report()->utrace_stop(). P continues, ptrace_attach() takes tasklist and sees PT_PTRACED. It calls utrace_control(E, UTRACE_DETACH). The signal is lost. In short. Perhaps I missed something, but I think it would be "safer" if ptrace_attach() did utrace_set_events() after setting PT_PTRACED, but this is not possible because attach sends SIGSTOP. That is why initially I was going to implement attach this way: utrace_attach_task(UTRACE_ATTACH_CREATE); write_lock(tasklist); if (child->ptrace) abort(); child->ptrace = PT_PTRACED; write_unlock(tasklist); utrace_set_events(...); send_sig_info(SIGSTOP); But then decided to revert this nightmire and keep the code simple. (Also. Unless I missed something, this means that even ptrace_detach(0) can't always use a plain UTRACE_DETACH. But lets discuss this later). Oleg. From oleg at redhat.com Tue Aug 18 17:02:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 18 Aug 2009 19:02:36 +0200 Subject: [PATCH 07] rework prepare_ptrace_attach/finish_ptrace_attach In-Reply-To: <20090818164400.GA13635@redhat.com> References: <20090817152258.GA10674@redhat.com> <20090818001522.206234730F@magilla.sf.frob.com> <20090818164400.GA13635@redhat.com> Message-ID: <20090818170236.GA13874@redhat.com> On 08/18, Oleg Nesterov wrote: > > In short. Perhaps I missed something, but I think it would be "safer" if > ptrace_attach() did utrace_set_events() after setting PT_PTRACED, but this > is not possible because attach sends SIGSTOP. That is why initially I was > going to implement attach this way: > > utrace_attach_task(UTRACE_ATTACH_CREATE); > > write_lock(tasklist); > if (child->ptrace) > abort(); > child->ptrace = PT_PTRACED; > write_unlock(tasklist); > > utrace_set_events(...); > send_sig_info(SIGSTOP); > > But then decided to revert this nightmire and keep the code simple. Hmm. Strange, but I didn't think of another option... ptrace_attach_task() can check ->ptrace == 0 ! Something like static int ptrace_attach_task(struct task_struct *tracee) { struct utrace_engine *engine; unsigned long events; engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, &ptrace_utrace_ops, NULL); if (unlikely(IS_ERR(engine))) { int err = PTR_ERR(engine); if (err != -ESRCH && err != -ERESTARTNOINTR) err = -EPERM ; return err; } // !!!!!!!!!!!!!!!!!!!!!!!! // We can rely on UTRACE_ATTACH_EXCLUSIVE and check ->ptrace lockless // !!!!!!!!!!!!!!!!!!!!!!!! if (unlikely(tracee->ptrace)) { utrace_control(engine, UTRACE_DETACH); utrace_engine_put(engine); return -EPERM; } /* * We need QUIESCE for resume handling, CLONE to check * for CLONE_PTRACE, other events are always reported. */ events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; /* * It can fail only if the tracee is dead, the caller * must notice this before setting PT_PTRACED. */ utrace_set_events(tracee, engine, events); utrace_engine_put(engine); return 0; } Then we change ptrace_attach: write_lock_irq(&tasklist_lock); retval = -EPERM; if (unlikely(task->exit_state)) goto unlock_tasklist; - if (task->ptrace) - goto unlock_tasklist; + BUG_ON(task->ptrace); .... unlock_tasklist: write_unlock_irq(&tasklist_lock); - if (retval) - ptrace_abort_attach(task); ptrace_traceme() can be changed the same way (except it should take parent's PF_EXITING into account). I'll recheck my thinking with a fresh head. But currently this looks like a good change to me. Even if (most probably) I was wrong and we shouldn't really worry about ptrace_abort_attach()'s subtleness. What do you think? Oleg. From oleg at redhat.com Tue Aug 18 18:17:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 18 Aug 2009 20:17:32 +0200 Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: <20090818045433.511254730F@magilla.sf.frob.com> References: <20090814144555.GA28295@redhat.com> <20090818045433.511254730F@magilla.sf.frob.com> Message-ID: <20090818181732.GA17634@redhat.com> On 08/17, Roland McGrath wrote: > > > Now. we should make sure that every user of UTRACE_DETACH frees > > engine->data. And, we have to introduce ptrace_report_reap() which > > should free it too. > > Right, or you can have a report_death callback Ah sorry, I meant ->report_death, not _reap. > (or even just report_quiesce > when passed UTRACE_EVENT(DEATH)) that always detaches. Hmm. Not sure I understand how can we do without hooking death or reap... > synchronizing with de_thread(), which is the one place that > ordinarily preempts the ptrace wait interference.) Not only de_thread(). If the tracee is killed, another thread can do wait()->release_task(). This means even _reap (instead of _death) can't save us. > I see two basic models for handling the engine lifetime issues in a utrace > engine. > > One way is where you do not normally hold a utrace_engine reference. > You get an initial one from UTRACE_ATTACH_CREATE when you do setup. > Once you have done utrace_set_events() and maybe utrace_control(), you > do utrace_engine_put() immediately. Then if you have callbacks that > use UTRACE_DETACH (or else have report_reap, where it's implicit) they > are responsible for engine->data. And indeed you must have some such > if you have an engine->data pointer that needs cleanup. This model is > probably a good fit for "passive" tracing, where the only thing you > really come back and do later is disable it (or for something simple > enough it doesn't need any cleanup for engine->data). Then you can do: > > engine = utrace_attach_task(task, UTRACE_ATTACH_MATCH_OPS, > &my_ops, NULL); > if (IS_ERR(engine)) ... > ret = utrace_control(task, engine, UTRACE_DETACH); > if (ret) ... > clean_up(engine->data); > > where -ESRCH/-EALREADY tell you that your report_reap/report_death > (also counts for report_quiesce in the report_death pass) either will > run, has run, or is running, so in that case you rely on them to do: > > clean_up(engine->data); > return UTRACE_DETACH; I must have missed something. Sure, it is more or less trivial to free engine->data safely. I mean, it is easy to avoid the double-free/etc problems. But I can't understand how the tracer can use ->data safely. Whatever the tracer does, the tracee can be killed at any moment. It can pass ->report_death/reap events under us. The tracer has 2 references, one to task_struct, another one to engine. That is why I still think a reference to engine should also pin engine->data, and I like very much the patch you sent. > The second model is where you normally hold a utrace_engine reference > to represent the life of your data structure, separate from the > implicit utrace_engine reference for being attached. The engine uses > the rule that the code that drops the last engine reference cleans up > the data structure, rather than the code that detaches doing that. And this means we need some hairy tricks. Perhaps I am overestimating this problem and these tricks are not that hairy. But still engine->release method is much simpler. > But I'm always open to adding things to make it easier > to write modules (and with fewer bugs), Yes! > > I strongly believe that ->data should be freed by utrace_engine_put(). > > If you have the reference to engine, engine->data must be stable. > > Well, that's a rule you can decide you want for your engine's handling > of its ->data, sure. You can in fact do that already, since you really > are in control of all the gets and puts. There is one put that's > implicit in detach, but you always either choose to detach or at least > could be notified. All other gets and puts are what your engine's code > chose to do. Yes sure. If you don't apply your patch which uses ops->release(), then I am going to add engine->data->in_use for reports which return UTRACE_DETACH or ->report_death. If the tracer needs engine->data it should use ptrace_get_context/ptrace_put_context. I am not sure we can avoid taking utrace->lock for that... > > So, this patch adds engine->dtor and utrace_engine_set_dtor() helper. > > The proper interface for this is just to add .release to utrace_engine_ops. > Because of how we fiddle the fields in detach, we'd still need to put the > function pointer into struct utrace_engine at some point in the > implementation. But the API doesn't really need to know about that. Yes, agreed. > > Afaics, unless a module intentionally leaks utrace_engine, it can safely > > use ->dtor() which lives in ->module_core. But at least it can always > > use ->dtor = kfree. > > I've never really figured out all the issues about module unloading for > utrace. I assume that's what you're referring to here. The two obvious > safe paths would seem to be either holding module refs whenever an > engine is attached (or now, until your release hook is called), or > synchronously detaching all engines (plus utrace_barrier et al) in the > module_exit function. Yes. Oleg. From roland at redhat.com Tue Aug 18 20:07:20 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 18 Aug 2009 13:07:20 -0700 (PDT) Subject: [PATCH] utrace_control: return -EINVAL for missing UTRACE_EVENT(QUIESCE) In-Reply-To: Oleg Nesterov's message of Tuesday, 18 August 2009 16:34:53 +0200 <20090818143453.GA7522@redhat.com> References: <20090818023307.F0A954730F@magilla.sf.frob.com> <20090818143453.GA7522@redhat.com> Message-ID: <20090818200720.8D4584730F@magilla.sf.frob.com> (I've dropped Srikar's address from the CC since it bounces. I hope he's reading the list.) > Unfortunately, this doesn't help if a module doesn't use utrace_control() > but just returns UTRACE_SINGLESTEP/etc. Like Srikar's test-case does. Yes. I thought about adding a WARN_ON or something. But I think it would just wind up being confusing or overlooked. > But I guess we can do nothing in this case, except perhaps we could add > pr_debug() into finish_callback(). I dunno. And in any case, the warning > from finish_callback() can't be always correct. I'm not sure what you mean here about "always correct". It is always correct that you should not use UTRACE_SINGLESTEP without setting up a callback. It might happen to be the case that it won't fail for lack of the callback, but that is just luck and your module is still incorrect for attempting it. Thanks, Roland From roland at redhat.com Tue Aug 18 20:31:52 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 18 Aug 2009 13:31:52 -0700 (PDT) Subject: [PATCH 08] change ptrace_traceme() to use the new helpers, kill prepare/finish attach In-Reply-To: Oleg Nesterov's message of Tuesday, 18 August 2009 17:17:24 +0200 <20090818151724.GD7522@redhat.com> References: <20090817152300.GA10678@redhat.com> <20090818003130.5439F4730F@magilla.sf.frob.com> <20090818151724.GD7522@redhat.com> Message-ID: <20090818203152.40F814730F@magilla.sf.frob.com> > Yes. But we attach to parent->parent, not to parent == current. Ah yes, I see your point. > In short: ptrace_report_clone() should "copy" the tracing state from > current to child when needed. And it should never attach if current > is not traced. Correct. > In particular, this means that > > if (event || (clone_flags & CLONE_PTRACE)) { > child_engine = utrace_attach_task(child, UTRACE_ATTACH_CREATE ... > > is not right. CLONE_PTRACE should be ignored unless task_ptrace(current). Ok, well this is implicitly assuming that ptrace won't properly detach its utrace engine when it should. In the case of PTRACE_DETACH, the tracee (potential parent, here) must be stopped, so it cannot be forking at the time. So you must be worried only about the exit_ptrace() case. The code triggered from report_clone that adds the new child to the tracer's tracees list has to synchronize with exit_ptrace() anyway. So that logic should also cover setup/teardown of the utrace engine. Thanks, Roland From fche at redhat.com Tue Aug 18 20:47:59 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Tue, 18 Aug 2009 16:47:59 -0400 Subject: [PATCH] utrace_control: return -EINVAL for missing UTRACE_EVENT(QUIESCE) In-Reply-To: <20090818200720.8D4584730F@magilla.sf.frob.com> References: <20090818023307.F0A954730F@magilla.sf.frob.com> <20090818143453.GA7522@redhat.com> <20090818200720.8D4584730F@magilla.sf.frob.com> Message-ID: <20090818204759.GC19793@redhat.com> Hi - > [...] I'm not sure what you mean here about "always correct". It is > always correct that you should not use UTRACE_SINGLESTEP without > setting up a callback. [...] I wonder if utrace could be more helpful here. If an engine just wants to single-step from some other callback, forcing it to have a quiesce callback just to re-re-re-repeat what it already asked for seems like make-work. Could utrace instead remember the last instruction received either via utrace_control() or from a real callback, and have utrace supply a dummy echo-bot quiesce? - FChE From roland at redhat.com Tue Aug 18 20:54:19 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 18 Aug 2009 13:54:19 -0700 (PDT) Subject: [PATCH] utrace_control: return -EINVAL for missing UTRACE_EVENT(QUIESCE) In-Reply-To: Frank Ch. Eigler's message of Tuesday, 18 August 2009 16:47:59 -0400 <20090818204759.GC19793@redhat.com> References: <20090818023307.F0A954730F@magilla.sf.frob.com> <20090818143453.GA7522@redhat.com> <20090818200720.8D4584730F@magilla.sf.frob.com> <20090818204759.GC19793@redhat.com> Message-ID: <20090818205419.33B174730F@magilla.sf.frob.com> > I wonder if utrace could be more helpful here. If an engine just > wants to single-step from some other callback, forcing it to have a > quiesce callback just to re-re-re-repeat what it already asked for > seems like make-work. Could utrace instead remember the last > instruction received either via utrace_control() or from a real > callback, and have utrace supply a dummy echo-bot quiesce? That is essentially like the old API where these were sticky flag bits. The point is that if other engines are doing other things, you really need to see what they are doing and react. From roland at redhat.com Tue Aug 18 21:16:27 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 18 Aug 2009 14:16:27 -0700 (PDT) Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: Oleg Nesterov's message of Tuesday, 18 August 2009 20:17:32 +0200 <20090818181732.GA17634@redhat.com> References: <20090814144555.GA28295@redhat.com> <20090818045433.511254730F@magilla.sf.frob.com> <20090818181732.GA17634@redhat.com> Message-ID: <20090818211627.6F0274730F@magilla.sf.frob.com> > > (or even just report_quiesce > > when passed UTRACE_EVENT(DEATH)) that always detaches. > > Hmm. Not sure I understand how can we do without hooking death or reap... UTRACE_EVENT(QUIESCE) constitutes "hooking death". A report_quiesce (UTRACE_EVENT(DEATH)) call precedes the report_death call. > > synchronizing with de_thread(), which is the one place that > > ordinarily preempts the ptrace wait interference.) > > Not only de_thread(). If the tracee is killed, another thread can > do wait()->release_task(). This means even _reap (instead of _death) > can't save us. That really has nothing to do with utrace. That's another "you" path that you control and can make do what you need it to. But, it is immaterial to the point I made: you can use report_reap as the means to interlock with that too if you so chose. It seems like a goofy choice for that, since it would be your code->release_task()->utrace_release_task()->your report_reap() and you might as well just do your code->your code. > > I see two basic models for handling the engine lifetime issues in a utrace > > engine. > > > > One way is where you do not normally hold a utrace_engine reference. [...] > I must have missed something. > > Sure, it is more or less trivial to free engine->data safely. I mean, > it is easy to avoid the double-free/etc problems. > > But I can't understand how the tracer can use ->data safely. Whatever > the tracer does, the tracee can be killed at any moment. It can > pass ->report_death/reap events under us. What you missed is where I said this model is appropriate for situations where you don't need to do that: > > This model is > > probably a good fit for "passive" tracing, where the only thing you > > really come back and do later is disable it (or for something simple > > enough it doesn't need any cleanup for engine->data). > > The second model is where you normally hold a utrace_engine reference [...] > And this means we need some hairy tricks. That is an utterly vague blanket statement to make. > Yes sure. If you don't apply your patch which uses ops->release(), then I > am going to add engine->data->in_use for reports which return UTRACE_DETACH > or ->report_death. If the tracer needs engine->data it should use > ptrace_get_context/ptrace_put_context. I am not sure we can avoid taking > utrace->lock for that... I don't really follow this at all. Your ptrace code has nothing to do with utrace->lock, and never will. Thanks, Roland From roland at redhat.com Tue Aug 18 22:25:27 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 18 Aug 2009 15:25:27 -0700 (PDT) Subject: [PATCH 07] rework prepare_ptrace_attach/finish_ptrace_attach In-Reply-To: Oleg Nesterov's message of Tuesday, 18 August 2009 18:44:00 +0200 <20090818164400.GA13635@redhat.com> References: <20090817152258.GA10674@redhat.com> <20090818001522.206234730F@magilla.sf.frob.com> <20090818164400.GA13635@redhat.com> Message-ID: <20090818222527.6F5134730F@magilla.sf.frob.com> > Note that I don't really understand why I am worried ;) Nameless fears are the most effective ones! > C recieves a signal, notices task_utrace_flags(), calls utrace_get_signal(), > dequeues the signal, calls E->ops->ptrace_report_signal() which returns > UTRACE_STOP. Ah, right. The important point is it returns UTRACE_SIGNAL_IGN|UTRACE_STOP. I overlooked this case, or perhaps I was wrongly thinking that it used UTRACE_SIGNAL_HOLD. (It doesn't and can't, because it needs to distinguish the signal it already reported from a new one, and also because an unrelated new one with a different (lower) signal number could be dequeued first on the second round.) An implicit detach (i.e. exit_ptrace) must act like a PTRACE_DETACH,signr for the last-reported signal. In old ptrace, that is implicit just in the ->exit_code value left behind and picked up on resume. Your implementation of this can probably just use the same method as for a real PTRACE_DETACH,signr. Just pick up last_siginfo->si_signo and use it. > In short. Perhaps I missed something, but I think it would be "safer" if > ptrace_attach() did utrace_set_events() after setting PT_PTRACED, but this > is not possible because attach sends SIGSTOP. [...] I don't really understand why the SIGSTOP is your concern. No matter what, you send that last, after ptrace is wired up to catch it. > Hmm. Strange, but I didn't think of another option... > > ptrace_attach_task() can check ->ptrace == 0 ! Something like Sorry, I've lost track of what this flag (that really shouldn't exist at all) means in your version that's distinct from whether you have the ptrace_utrace_ops engine attached. Thanks, Roland From oleg at redhat.com Wed Aug 19 12:06:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 19 Aug 2009 14:06:28 +0200 Subject: [PATCH] utrace_control: return -EINVAL for missing UTRACE_EVENT(QUIESCE) In-Reply-To: <20090818200720.8D4584730F@magilla.sf.frob.com> References: <20090818023307.F0A954730F@magilla.sf.frob.com> <20090818143453.GA7522@redhat.com> <20090818200720.8D4584730F@magilla.sf.frob.com> Message-ID: <20090819120628.GA425@redhat.com> On 08/18, Roland McGrath wrote: > > > Unfortunately, this doesn't help if a module doesn't use utrace_control() > > but just returns UTRACE_SINGLESTEP/etc. Like Srikar's test-case does. > > Yes. I thought about adding a WARN_ON or something. But I think it would > just wind up being confusing or overlooked. Yes, agreed. > > But I guess we can do nothing in this case, except perhaps we could add > > pr_debug() into finish_callback(). I dunno. And in any case, the warning > > from finish_callback() can't be always correct. > > I'm not sure what you mean here about "always correct". It is always > correct that you should not use UTRACE_SINGLESTEP without setting up a > callback. Yes. But finish_callback() can race with utrace_set_events() which can clear QUIESCE after the callback returns UTRACE_SINGLESTEP, in this case the warning is wrong. Oleg. From oleg at redhat.com Wed Aug 19 12:33:18 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 19 Aug 2009 14:33:18 +0200 Subject: [PATCH 07] rework prepare_ptrace_attach/finish_ptrace_attach In-Reply-To: <20090818222527.6F5134730F@magilla.sf.frob.com> References: <20090817152258.GA10674@redhat.com> <20090818001522.206234730F@magilla.sf.frob.com> <20090818164400.GA13635@redhat.com> <20090818222527.6F5134730F@magilla.sf.frob.com> Message-ID: <20090819123318.GA632@redhat.com> On 08/18, Roland McGrath wrote: > > > C recieves a signal, notices task_utrace_flags(), calls utrace_get_signal(), > > dequeues the signal, calls E->ops->ptrace_report_signal() which returns > > UTRACE_STOP. > > Your implementation of this can probably just use the same method as for a > real PTRACE_DETACH,signr. Just pick up last_siginfo->si_signo and use it. Yes. Or we can simplify the code a bit (check ->ptrace in ptrace_attach_task) and make sure that after UTRACE_ATTACH_EXCLUSIVE ptrace_attach() can never fail and thus we should worry about detaching at all. Unless the tracee is killed, of course. But in this case we don't care and just return after "if (->exit_state)" check. > > In short. Perhaps I missed something, but I think it would be "safer" if > > ptrace_attach() did utrace_set_events() after setting PT_PTRACED, but this > > is not possible because attach sends SIGSTOP. [...] > > I don't really understand why the SIGSTOP is your concern. > No matter what, you send that last, after ptrace is wired up to catch it. Because the tracee must not dequeue and handle this SIGSTOP until it sees UTRACE_EVENT_SIGNAL_ALL in ->utrace_flags. > > ptrace_attach_task() can check ->ptrace == 0 ! Something like > > Sorry, I've lost track of what this flag (that really shouldn't exist at > all) means in your version that's distinct from whether you have the > ptrace_utrace_ops engine attached. Yes, ->ptrace should die. But we can't kill it right now. (I mean, I don't see how can we kill it before we have a more or less working ptrace code). Until we kill it, ptrace_attach pathes should - set PT_PTRACED for task_ptrace() callers in exit/signal/etc.c - check it to avoid the races with another tracer doing detach, iow simply to prevent __ptrace_link() before __ptrace_unlink(). So, ptrace_attach() can do utrace_attach_task(UTRACE_ATTACH_EXCLUSIVE, ptrace_utrace_ops); if (tracee->ptrace) { // We race with detach: a previous tracer already detached // its engine, but we can't __ptrace_link() yet. return -EPERM; } // Nobody can attach ptrace_utrace_ops now. This also means // nobody can set ->ptrace != 0 except us. utrace_set_events(...); write_lock(tasklist); tracee->ptrace = PT_PTRACED; __ptrace_link(); write_unlock(tasklist); Oleg. From oleg at redhat.com Wed Aug 19 12:47:07 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 19 Aug 2009 14:47:07 +0200 Subject: [PATCH 08] change ptrace_traceme() to use the new helpers, kill prepare/finish attach In-Reply-To: <20090818203152.40F814730F@magilla.sf.frob.com> References: <20090817152300.GA10678@redhat.com> <20090818003130.5439F4730F@magilla.sf.frob.com> <20090818151724.GD7522@redhat.com> <20090818203152.40F814730F@magilla.sf.frob.com> Message-ID: <20090819124707.GB632@redhat.com> On 08/18, Roland McGrath wrote: > > > In particular, this means that > > > > if (event || (clone_flags & CLONE_PTRACE)) { > > child_engine = utrace_attach_task(child, UTRACE_ATTACH_CREATE ... > > > > is not right. CLONE_PTRACE should be ignored unless task_ptrace(current). > > Ok, well this is implicitly assuming that ptrace won't properly detach its > utrace engine when it should. In the case of PTRACE_DETACH, the tracee > (potential parent, here) must be stopped, so it cannot be forking at the > time. So you must be worried only about the exit_ptrace() case. Yes. > The code triggered from report_clone that adds the new child to the > tracer's tracees list has to synchronize with exit_ptrace() anyway. So > that logic should also cover setup/teardown of the utrace engine. Yes. That is why I mentioned ptrace_traceme(), it has to avoid the similar races with the exiting parent. Oleg. From oleg at redhat.com Wed Aug 19 13:53:23 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 19 Aug 2009 15:53:23 +0200 Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: <20090818211627.6F0274730F@magilla.sf.frob.com> References: <20090814144555.GA28295@redhat.com> <20090818045433.511254730F@magilla.sf.frob.com> <20090818181732.GA17634@redhat.com> <20090818211627.6F0274730F@magilla.sf.frob.com> Message-ID: <20090819135323.GC632@redhat.com> On 08/18, Roland McGrath wrote: > > > > (or even just report_quiesce > > > when passed UTRACE_EVENT(DEATH)) that always detaches. > > > > Hmm. Not sure I understand how can we do without hooking death or reap... > > UTRACE_EVENT(QUIESCE) constitutes "hooking death". Ah yes, utrace_report_death() doesn't call ->report_death() directly, it does REPORT_CALLBACKS(). > > I must have missed something. > > > > But I can't understand how the tracer can use ->data safely. Whatever > > the tracer does, the tracee can be killed at any moment. It can > > pass ->report_death/reap events under us. > > What you missed is where I said this model is appropriate for situations > where you don't need to do that: Yes, I did miss that. > > > The second model is where you normally hold a utrace_engine reference > [...] > > And this means we need some hairy tricks. > > That is an utterly vague blanket statement to make. Agreed. Let me try again. > This model seems like a better fit for ptrace to me. The anchoring data > structure is the tracer's tracees list, which links together the > ptrace_context structs. A live ptrace_context has an engine pointer and > a ref for it. OK. Not that I really understand this all in details, but OK. But. Do you think we should do this right now? I don't. Imho, we need a lot of changes before this. We need the working code first. I just can't understand how can we do the necessary changes to solve (say) the problems with de_thread() now, when it is not clear (to me) how the basic/core ptrace code will look. And to have the more or less working code, we need engine->data which can be used by tracer. Do you have any suggestion what can we do right now? (assuming you won't apply your ops->release patch). > > Yes sure. If you don't apply your patch which uses ops->release(), then I > > am going to add engine->data->in_use for reports which return UTRACE_DETACH > > or ->report_death. If the tracer needs engine->data it should use > > ptrace_get_context/ptrace_put_context. I am not sure we can avoid taking > > utrace->lock for that... > > I don't really follow this at all. > Your ptrace code has nothing to do with utrace->lock, and never will. Yes, agreed. ptrace should not use utrace->lock. But currently I don't see how to do this without utrace->lock. Or without rcu + refcnt. Oleg. From oleg at redhat.com Wed Aug 19 17:36:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 19 Aug 2009 19:36:52 +0200 Subject: [PATCHES 09-10] attach ->ptrace tweaks, rework clone/attach Message-ID: <20090819173652.GA25164@redhat.com> I was going to do this later. But since I didn't find a simple solution for engine->data problems yet (and to be honest I hope the discussion about engine->realease is not finished ;), I am sending these changes to make at least small progress. Oleg. From oleg at redhat.com Wed Aug 19 17:36:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 19 Aug 2009 19:36:54 +0200 Subject: [PATCH 09] move ->ptrace == 0 checks to ptrace_attach_task() Message-ID: <20090819173654.GA25171@redhat.com> Until we kill ->ptrace, attach must ensure ->ptrace == 0 to avoid the races with detach. We can move these checks to ptrace_attach_task() from the callers, and we can do this check lockless. >From now ptrace_abort_attach() is only called when the tracee had no chance to execute any callback, a simple UTRACE_DETACH is enough. ptrace_attach() doesn't need ptrace_abort_attach() at all, if the tracee is killed we don't care about attached engine. --- kernel/ptrace.c | 67 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 31 deletions(-) --- PU/kernel/ptrace.c~09_MV_PTRACE_CK 2009-08-19 16:49:25.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-19 17:41:18.000000000 +0200 @@ -471,35 +471,45 @@ static int ptrace_attach_task(struct tas { struct utrace_engine *engine; unsigned long events; + int err = -EPERM; engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, &ptrace_utrace_ops, NULL); if (unlikely(IS_ERR(engine))) { - int err = PTR_ERR(engine); - if (err != -ESRCH && err != -ERESTARTNOINTR) - err = -EPERM ; + if (PTR_ERR(engine) == -ESRCH || + PTR_ERR(engine) == -ERESTARTNOINTR) + err = PTR_ERR(engine); return err; } + /* - * We need QUIESCE for resume handling, CLONE to check - * for CLONE_PTRACE, other events are always reported. - */ - events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | - UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; - /* - * It can fail only if the tracee is dead, the caller - * must notice this before setting PT_PTRACED. + * Check ->ptrace to make sure we don't race with the previous + * tracer which didn't finish detach. If it is clear, nobody + * can change it except us due to UTRACE_ATTACH_EXCLUSIVE. */ - utrace_set_events(tracee, engine, events); + if (likely(!tracee->ptrace)) { + /* + * We need QUIESCE for resume handling, CLONE to check + * for CLONE_PTRACE, other events are always reported. + */ + events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | + UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; + /* + * It can fail only if the tracee is dead, the caller + * must notice this before setting PT_PTRACED. + */ + utrace_set_events(tracee, engine, events); + err = 0; + } + utrace_engine_put(engine); - return 0; + return err; } static void ptrace_abort_attach(struct task_struct *tracee) { - /* XXX we raced with detach. Double check UTRACE_DETACH is enough */ ptrace_detach_task(tracee, 0); } @@ -613,9 +623,8 @@ int ptrace_attach(struct task_struct *ta retval = -EPERM; if (unlikely(task->exit_state)) goto unlock_tasklist; - if (task->ptrace) - goto unlock_tasklist; + BUG_ON(task->ptrace); task->ptrace = PT_PTRACED; if (capable(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; @@ -626,8 +635,6 @@ int ptrace_attach(struct task_struct *ta retval = 0; unlock_tasklist: write_unlock_irq(&tasklist_lock); - if (retval) - ptrace_abort_attach(task); unlock_creds: mutex_unlock(&task->cred_guard_mutex); out: @@ -650,19 +657,17 @@ int ptrace_traceme(void) ret = -EPERM; write_lock_irq(&tasklist_lock); - /* Are we already being traced? */ - if (!current->ptrace) { - ret = security_ptrace_traceme(current->parent); - /* - * Check PF_EXITING to ensure ->real_parent has not passed - * exit_ptrace(). Otherwise we don't report the error but - * pretend ->real_parent untraces us right after return. - */ - if (!ret && !(current->real_parent->flags & PF_EXITING)) { - current->ptrace = PT_PTRACED; - __ptrace_link(current, current->real_parent); - detach = false; - } + BUG_ON(current->ptrace); + ret = security_ptrace_traceme(current->parent); + /* + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. + */ + if (!ret && !(current->real_parent->flags & PF_EXITING)) { + current->ptrace = PT_PTRACED; + __ptrace_link(current, current->real_parent); + detach = false; } write_unlock_irq(&tasklist_lock); From oleg at redhat.com Wed Aug 19 17:36:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 19 Aug 2009 19:36:57 +0200 Subject: [PATCH 10] ptrace_report_clone: rework auto-attaching Message-ID: <20090819173657.GA25174@redhat.com> Change ptrace_report_clone() to do all attach work itself. Note that this allows to greatly simplify do_fork() path wrt tracehooks. For example we do not need tracehook_prepare_clone() at all. tracehook_finish_clone() does not need tasklist. copy_process() does not need "int traced". Both ptrace_report_clone() and ptrace_clone_attach() need more work. ptrace_clone_attach() will be changed once we add engine->data. --- include/linux/ptrace.h | 4 --- include/linux/tracehook.h | 8 ------ kernel/ptrace.c | 56 ++++++++++++++++++++++++++++------------------ 3 files changed, 35 insertions(+), 33 deletions(-) --- PU/include/linux/ptrace.h~10_CLONE_ATTACH 2009-08-19 18:05:15.000000000 +0200 +++ PU/include/linux/ptrace.h 2009-08-19 18:05:34.000000000 +0200 @@ -147,10 +147,6 @@ static inline void ptrace_init_task(stru INIT_LIST_HEAD(&child->ptraced); child->parent = child->real_parent; child->ptrace = 0; - if (unlikely(ptrace)) { - child->ptrace = current->ptrace; - ptrace_link(child, current->parent); - } } /** --- PU/include/linux/tracehook.h~10_CLONE_ATTACH 2009-08-13 17:51:52.000000000 +0200 +++ PU/include/linux/tracehook.h 2009-08-19 18:34:37.000000000 +0200 @@ -264,14 +264,6 @@ static inline void tracehook_report_clon { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE))) utrace_report_clone(clone_flags, child); - if (unlikely(task_ptrace(child))) { - /* - * It doesn't matter who attached/attaching to this - * task, the pending SIGSTOP is right in any case. - */ - sigaddset(&child->pending.signal, SIGSTOP); - set_tsk_thread_flag(child, TIF_SIGPENDING); - } } /** --- PU/kernel/ptrace.c~10_CLONE_ATTACH 2009-08-19 17:41:18.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-19 19:12:32.000000000 +0200 @@ -39,6 +39,8 @@ void __ptrace_link(struct task_struct *c } static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */ +static int ptrace_attach_task(struct task_struct *tracee); +static void ptrace_abort_attach(struct task_struct *tracee); static void ptrace_detach_task(struct task_struct *child, int sig) { @@ -211,6 +213,37 @@ static u32 ptrace_report_exit(enum utrac return utrace_ptrace_event(task, PTRACE_EVENT_EXIT, *code); } +static void ptrace_clone_attach(struct task_struct *parent, + struct task_struct *child) +{ + struct task_struct *tracer; + bool abort = true; + + if (!parent->ptrace) + return; + if (unlikely(ptrace_attach_task(child))) { + WARN_ON(1); + return; + } + + write_lock_irq(&tasklist_lock); + tracer = parent->parent; + if (!(tracer->flags & PF_EXITING) && parent->ptrace) { + child->ptrace = parent->ptrace; + __ptrace_link(child, tracer); + abort = false; + } + write_unlock_irq(&tasklist_lock); + if (unlikely(abort)) { + ptrace_abort_attach(child); + return; + } + + sigaddset(&child->pending.signal, SIGSTOP); + set_tsk_thread_flag(child, TIF_SIGPENDING); + ptrace_update_utrace(child, NULL); +} + static u32 ptrace_report_clone(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *parent, @@ -218,7 +251,6 @@ static u32 ptrace_report_clone(enum utra struct task_struct *child) { int event; - struct utrace_engine *child_engine; if ((clone_flags & CLONE_VFORK) && (parent->ptrace & PT_TRACE_VFORK_DONE)) { @@ -254,26 +286,8 @@ static u32 ptrace_report_clone(enum utra * Any of these reports implies auto-attaching the new child. * So does CLONE_PTRACE, even with no event to report. */ - if (event || (clone_flags & CLONE_PTRACE)) { - child_engine = utrace_attach_task(child, UTRACE_ATTACH_CREATE | - UTRACE_ATTACH_EXCLUSIVE | - UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, - NULL); - if (unlikely(IS_ERR(child_engine))) { - WARN_ON(1); /* XXX */ - } else { - BUG_ON(!child->ptrace); - /* XXX already set by old ptrace code - task_lock(child); - child->ptrace = parent->ptrace; - child->parent = parent->parent; - task_unlock(child); - */ - ptrace_update_utrace(child, child_engine); - utrace_engine_put(child_engine); - } - } + if (event || (clone_flags & CLONE_PTRACE)) + ptrace_clone_attach(parent, child); if (event) return utrace_ptrace_event(parent, event, child->pid); From srikar at linux.vnet.ibm.com Wed Aug 19 17:55:33 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 19 Aug 2009 23:25:33 +0530 Subject: [PATCH 0/4] Fixes to gdbstub. Message-ID: <20090819175533.10199.83118.sendpatchset@srdronam.in.ibm.com> Hi Frank, Please review the set of patches for gdbstub. These are based on your maintained tree. utrace-next/utrace-gdbstub-uprobes branch. (1afe698c3228e67c43db6343b383a13e27e7f11a) I have explicitly run checkpatch.pl to remove any formatting warnings / errors. However the formatting in these patches may be different from other parts of the code. At this time we have couple of known issues. 1. register_uprobe/unregister_uprobe may cause deadlock( I am looking at this). 2. Even when we havent registered a breakpoint, there is a request for breakpoint. (Not sure why gdbstub is asking for the breakpoint which is never hit). 3. Sometimes entering data when the first breakpoint gets hit results in SIGSTOP being sent to the traced process. 4. Uprobes may do postprocessing even when singlestep hasnt happened. (I am looking at this too). 5. Supporting Multithreaded programs. Also we might have to do cleaning up of code as per checkpatch.pl before submission to LKML. Subject: [PATCH 0/4] Fixes to gdbstub. File: /tmp/gdbstub-patches/1/intro Subject: [PATCH 1/4] Fix report signal callback to work more reliably. File: /tmp/gdbstub-patches/1/gdbstub_signal_callback.patch Subject: [PATCH 2/4] Fix possible double detach of engine File: /tmp/gdbstub-patches/1/fix_double_detach.patch Subject: [PATCH 3/4] Unregister uprobes after detach gdbstub engine File: /tmp/gdbstub-patches/1/unreg_after_detach.patch Subject: [PATCH 4/4] Stop once even for multiple interrupt requests File: /tmp/gdbstub-patches/1/only_stop_once.patch -- Thanks and Regards Srikar Dronamraju From srikar at linux.vnet.ibm.com Wed Aug 19 17:55:44 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 19 Aug 2009 23:25:44 +0530 Subject: [PATCH 1/4] Fix report signal callback to work more reliably. In-Reply-To: <20090819175533.10199.83118.sendpatchset@srdronam.in.ibm.com> References: <20090819175533.10199.83118.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090819175544.10199.30190.sendpatchset@srdronam.in.ibm.com> This patch modifies report_signal callback for gdbstub and uprobe_handler. Previously we would alert in uprobe_handler that gdb should stop the thread. For this we expected the thread to stop before it singlestepped. However this seems unreliable and also we werent doing a explicit UTRACE_STOP. With this patch, report_signal callback has enuf intelligence to know if SIGTRAPS were occurring at the address where gdb requested for breakpoints. Now we have a dummy uprobe_handler. Signed-off-by: Srikar Dronamraju diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index 0c84afb..f7833dc 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -231,51 +231,33 @@ static void push_output_packet (struct gdb_connection *p, const char *s) /* ------------------------------------------------------------------------ */ - - -#ifdef CONFIG_HAVE_UPROBES -/* uprobe callback */ -void gdb_uprobe_handler (struct uprobe* up, struct pt_regs* regs) +static bool can_gdb_handle_sigtrap(struct pt_regs *regs, + struct gdb_connection *p) { - struct gdb_connection *p = NULL; - struct list_head *l; unsigned long bkpt = ubp_get_bkpt_addr (regs); struct task_struct *task = current; - pr_debug ("uprobe hit for %d, pc=%p\n", task->pid, (void*)bkpt); - - /* Find the right gdb_connection* for this task. */ - mutex_lock (& gdb_connections_mutex); - list_for_each(l, &gdb_connections) { - p = list_entry (l, struct gdb_connection, link); - if (p->target == task_tgid_nr(task)) { - struct list_head *l; - struct list_head *l2; - struct gdb_uprobe *gup = NULL; - - mutex_unlock (& gdb_connections_mutex); - mutex_lock (& p->output_mutex); - - list_for_each_safe(l, l2, & p->uprobes) { - gup = list_entry (l, struct gdb_uprobe, link); - pr_debug ("considering addr=%p %s\n", (void*) gup->up.vaddr, - gup->disarmed_p ? "disarmed" : ""); - if (gup->up.vaddr == bkpt && !gup->disarmed_p) { - p->at_quiesce_do = UTRACE_STOP; - snprintf (p->stopcode, GDB_BUFMAX, "S%02x", 5); /* SIGTRAP */ - push_output_packet (p, p->stopcode); - /* NB: This thread will be shortly stopped, even before - * uprobes get a chance to singlestep, or to complete an - * unregister_uprobe(). - */ - } - } + if (p->target == task_tgid_nr(task)) { + struct list_head *l; + struct list_head *l2; + struct gdb_uprobe *gup = NULL; + + list_for_each_safe(l, l2, &p->uprobes) { + gup = list_entry(l, struct gdb_uprobe, link); + pr_debug("considering addr=%p %s\n", + (void *)gup->up.vaddr, + gup->disarmed_p ? "disarmed" : ""); + if (gup->up.vaddr == bkpt && !gup->disarmed_p) + return true; + } + } + return false; +} - mutex_unlock (& p->output_mutex); - return; - } - } - mutex_unlock (& gdb_connections_mutex); +#ifdef CONFIG_HAVE_UPROBES +/* uprobe callback */ +void gdb_uprobe_handler(struct uprobe *up, struct pt_regs *regs) +{ } #endif /* CONFIG_HAVE_UPROBES */ @@ -405,14 +387,14 @@ u32 gdb_utrace_report_signal(u32 action, break; case UTRACE_SIGNAL_REPORT: /* case 3 */ - if (p->stop_signals>0) { + if (p->stop_signals > 0) { p->stop_signals --; snprintf (p->stopcode, GDB_BUFMAX, "S%02x", 2); /* SIGINT */ push_output_packet (p, p->stopcode); p->at_quiesce_do = UTRACE_STOP; ret = UTRACE_STOP | UTRACE_SIGNAL_IGN; } else { - ret = UTRACE_RESUME | utrace_signal_action(action); + ret = p->at_quiesce_do | utrace_signal_action(action); } break; @@ -424,14 +406,17 @@ u32 gdb_utrace_report_signal(u32 action, case UTRACE_SIGNAL_TSTP: #ifdef CONFIG_HAVE_UPROBES if (info->si_signo == SIGTRAP) { /* case 2a */ - unsigned long bkpt = ubp_get_bkpt_addr (regs); - /* XXX: search for nearby uprobes. */ - (void) bkpt; - - /* NB: don't set p->at_quiesce_do, since the uprobes_handler - might have already been called, and set UTRACE_STOP there. */ - ret = UTRACE_RESUME; /* Let uprobes consume the signal. */ - break; + if (can_gdb_handle_sigtrap(regs, p)) { + p->at_quiesce_do = UTRACE_STOP; + /* SIGTRAP */ + snprintf(p->stopcode, GDB_BUFMAX, "S%02x", 5); + push_output_packet(p, p->stopcode); + ret = UTRACE_STOP | + utrace_signal_action(action); + } else + ret = UTRACE_RESUME | + utrace_signal_action(action); + break; } #endif /* CONFIG_HAVE_UPROBES */ if (p->pass_signals > 0 /*&& kern_p*/) { /* case 4 */ @@ -443,7 +428,7 @@ u32 gdb_utrace_report_signal(u32 action, map_signal_kern2gdb(info->si_signo)); push_output_packet (p, p->stopcode); p->at_quiesce_do = UTRACE_STOP; - ret = UTRACE_STOP; + ret = UTRACE_STOP | utrace_signal_action(action); } break; } @@ -1327,7 +1312,6 @@ again: mutex_unlock(&p->output_mutex); goto again; } - len = min (count, (size_t)(p->output_buf_size - p->output_buf_read)); if (copy_to_user (buf, & p->output_buf[p->output_buf_read], len)) { rc = -EFAULT; From srikar at linux.vnet.ibm.com Wed Aug 19 17:55:57 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 19 Aug 2009 23:25:57 +0530 Subject: [PATCH 2/4] Fix possible double detach of engine In-Reply-To: <20090819175533.10199.83118.sendpatchset@srdronam.in.ibm.com> References: <20090819175533.10199.83118.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090819175557.10199.20618.sendpatchset@srdronam.in.ibm.com> commit bf679f65284b834b455e8453d10616073ff58d2c Author: Srikar Dronamraju Date: Tue Aug 18 18:15:49 2009 +0530 detach fix Saw a Oops message BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 IP: [] get_utrace_lock+0x43/0x115 I figured out the reason for the oops message as "2nd parameter (engine) to utrace_set_events as NULL." Call sequence is as below: - traced process exits resulting in gdb_utrace_report_death being called. - gdb_utrace_report_death sets p->engine to NULL and returns UTRACE_DETACH. - gdb calls release callback (proc_gdb_release() which results in - utrace_set_events and utrace_control(..,UTRACE_DETACH) with engine being set to NULL resulting in OOPS. Also we were explicitly decrementing reference to engine even when we havent explicitly incremented a reference. This patch - Doesnt detach from release callback if the engine is already detached. - removes explicit reference decrement. - removes setting engine to NULL in gdb_utrace_report_death(). Signed-off-by: Srikar Dronamraju diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index f7833dc..8cf2b0f 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -497,8 +497,6 @@ u32 gdb_utrace_report_death(struct utrace_engine *engine, snprintf (p->stopcode, GDB_BUFMAX, "X%2x", (unsigned)(signal & 0xFF)); push_output_packet (p, p->stopcode); - p->engine = NULL; - #ifdef CONFIG_HAVE_UPROBES { struct list_head *l; @@ -1245,11 +1243,11 @@ static int proc_gdb_release(struct inode *inode, struct file *filp) } #endif /* CONFIG_HAVE_UPROBES */ - if (task == NULL) { + if (task == NULL) { /* The thread is already gone; report_death was already called. */ - pr_debug ("gdb %d releasing old\n", p->target); - } else { - pr_debug ("gdb %d releasing current\n", p->target); + pr_debug("gdb %d releasing old\n", p->target); + } else if (p->at_quiesce_do != UTRACE_DETACH) { + pr_debug("gdb %d releasing current\n", p->target); ret = utrace_set_events(task, p->engine, 0); if (ret == -EINPROGRESS) @@ -1259,8 +1257,6 @@ static int proc_gdb_release(struct inode *inode, struct file *filp) ret = utrace_control(task, p->engine, UTRACE_DETACH); /* => RESUME */ if (ret == -EINPROGRESS) ret = utrace_barrier(task, p->engine); - - utrace_engine_put (p->engine); } list_del(&p->link); From srikar at linux.vnet.ibm.com Wed Aug 19 17:56:07 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 19 Aug 2009 23:26:07 +0530 Subject: [PATCH 3/4] Unregister uprobes after detach gdbstub engine In-Reply-To: <20090819175533.10199.83118.sendpatchset@srdronam.in.ibm.com> References: <20090819175533.10199.83118.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090819175607.10199.73807.sendpatchset@srdronam.in.ibm.com> commit 90cc0931707c99459aea0f6601d7f5ce2756dbd8 Author: Srikar Dronamraju Date: Wed Aug 19 10:26:00 2009 +0530 While releasing, unregister uprobes if any after detach Currently because of the way uprobes works, (register/unregister may deadlock if one of the threads of this process is expecting a singlestep to complete and someother engine as already stopped that thread. [ I am looking into this issue]) gdb requests register and unregister of all probes when it hits any breakpoints. However gdb through another engine stops the thread. At this time uprobes may have initiated singlestep but yet to be completed. Frank has converted register/unregister of breakpoints to setting/unsetting a flag. Hence once registered, unregister of probes occurs at closing of gdb connection. At that time the deadlock situation may again occur. This patch moves the unregister of uprobes (which is independent of the gdbstub engine) to after detach. This is a simple and harmless workaround for now. Signed-off-by: Srikar Dronamraju diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index 8cf2b0f..7d32264 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -1228,21 +1228,6 @@ static int proc_gdb_release(struct inode *inode, struct file *filp) int ret = 0; mutex_lock (& gdb_connections_mutex); - -#ifdef CONFIG_HAVE_UPROBES - { - struct list_head *l; - struct list_head *l2; - list_for_each_safe(l, l2, & p->uprobes) { - struct gdb_uprobe *gup = list_entry (l, struct gdb_uprobe, link); - if (task) /* Not dead yet. */ - unregister_uprobe (& gup->up); - list_del (& gup->link); - kfree (gup); - } - } -#endif /* CONFIG_HAVE_UPROBES */ - if (task == NULL) { /* The thread is already gone; report_death was already called. */ pr_debug("gdb %d releasing old\n", p->target); @@ -1259,6 +1244,20 @@ static int proc_gdb_release(struct inode *inode, struct file *filp) ret = utrace_barrier(task, p->engine); } +#ifdef CONFIG_HAVE_UPROBES + { + struct list_head *l, *l2; + list_for_each_safe(l, l2, &p->uprobes) { + struct gdb_uprobe *gup = + list_entry(l, struct gdb_uprobe, link); + if (task) /* Not dead yet. */ + unregister_uprobe(&gup->up); + list_del(&gup->link); + kfree(gup); + } + } +#endif /* CONFIG_HAVE_UPROBES */ + list_del(&p->link); kfree(p); From srikar at linux.vnet.ibm.com Wed Aug 19 17:56:17 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 19 Aug 2009 23:26:17 +0530 Subject: [PATCH 4/4] Stop once even for multiple interrupt requests In-Reply-To: <20090819175533.10199.83118.sendpatchset@srdronam.in.ibm.com> References: <20090819175533.10199.83118.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090819175617.10199.6446.sendpatchset@srdronam.in.ibm.com> commit bd86cff51a2f221b6cb10649212e5392aea7bcb7 Author: Srikar Dronamraju Date: Wed Aug 19 11:43:53 2009 +0530 We only need to intimate gdb once if we get multiple requests for look There can be multiple stop requests before gdb gets control. However continue from gdb can resulting in the process again being stopped because we are just decrementing the count and not clearing it. I dont see a reason why gdb should return control after asked to continue unless there is a new request for stop. The other way to do this could be to make stop_signals a bool instead of integer. Signed-off-by: Srikar Dronamraju diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index 7d32264..5d18759 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -388,7 +388,7 @@ u32 gdb_utrace_report_signal(u32 action, case UTRACE_SIGNAL_REPORT: /* case 3 */ if (p->stop_signals > 0) { - p->stop_signals --; + p->stop_signals = 0; snprintf (p->stopcode, GDB_BUFMAX, "S%02x", 2); /* SIGINT */ push_output_packet (p, p->stopcode); p->at_quiesce_do = UTRACE_STOP; From oleg at redhat.com Wed Aug 19 18:01:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 19 Aug 2009 20:01:28 +0200 Subject: [PATCH] utrace: utrace_finish_vfork: check ->vfork_stop lockless Message-ID: <20090819180128.GA26296@redhat.com> If ->vfork_stop was set, it was set by us, no need to take utrace->lock to check it. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) --- PU/kernel/utrace.c~UTRACE_1_vfork_stop 2009-08-19 14:00:57.000000000 +0200 +++ PU/kernel/utrace.c 2009-08-19 19:43:58.000000000 +0200 @@ -1601,10 +1601,8 @@ void utrace_finish_vfork(struct task_str { struct utrace *utrace = task_utrace_struct(task); - spin_lock(&utrace->lock); - if (!utrace->vfork_stop) - spin_unlock(&utrace->lock); - else { + if (utrace->vfork_stop) { + spin_lock(&utrace->lock); utrace->vfork_stop = 0; spin_unlock(&utrace->lock); utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ From oleg at redhat.com Wed Aug 19 18:18:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 19 Aug 2009 20:18:51 +0200 Subject: [PATCH] utrace: utrace_finish_vfork: check ->vfork_stop lockless In-Reply-To: <20090819180128.GA26296@redhat.com> References: <20090819180128.GA26296@redhat.com> Message-ID: <20090819181851.GA26313@redhat.com> On 08/19, Oleg Nesterov wrote: > > If ->vfork_stop was set, it was set by us, no need to take utrace->lock > to check it. Oh. Yes, but... I hope I missed something, but I'm _afraid_ we may have problems. Looks like we can almost never use utrace->xxx:1 fields without ->lock. Suppose that, for example, utrace_control(UTRACE_REPORT) does utrace->report = 1; But report/interrupt/etc are all bitfields :1. Doesn't this mean compiler can do anything it wants with the word where these bitfields live? Can't it temporary (say) clear ->interrupt while setting ->report ? IOW, as a perl programmer I need your help with "C". Do we have any guarantee that compiler will always update the word "as a whole" ? Oleg. From roland at redhat.com Thu Aug 20 00:13:47 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 19 Aug 2009 17:13:47 -0700 (PDT) Subject: [PATCH] utrace_control: return -EINVAL for missing UTRACE_EVENT(QUIESCE) In-Reply-To: Oleg Nesterov's message of Wednesday, 19 August 2009 14:06:28 +0200 <20090819120628.GA425@redhat.com> References: <20090818023307.F0A954730F@magilla.sf.frob.com> <20090818143453.GA7522@redhat.com> <20090818200720.8D4584730F@magilla.sf.frob.com> <20090819120628.GA425@redhat.com> Message-ID: <20090820001348.045BA4730F@magilla.sf.frob.com> > Yes. But finish_callback() can race with utrace_set_events() which can > clear QUIESCE after the callback returns UTRACE_SINGLESTEP, in this case > the warning is wrong. Ah! I see your point. Thanks, Roland From divulgacao at refrimur.com Thu Aug 20 05:29:06 2009 From: divulgacao at refrimur.com (Refrimur) Date: Thu, 20 Aug 2009 02:29:06 -0300 Subject: Refrimur Agosto 2009 Message-ID: An HTML attachment was scrubbed... URL: From viamail at zigpack.com Thu Aug 20 16:19:24 2009 From: viamail at zigpack.com (=?windows-1252?Q?Transporte_e_servi=E7os?=) Date: Thu, 20 Aug 2009 16:19:24 -0000 Subject: =?windows-1252?q?Solu=E7=F5es_Flex=EDveis?= Message-ID: An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: benogue.png Type: image/png Size: 21115 bytes Desc: not available URL: From oleg at redhat.com Thu Aug 20 18:21:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 20 Aug 2009 20:21:49 +0200 Subject: [PATCH 09] move ->ptrace == 0 checks to ptrace_attach_task() In-Reply-To: <20090819173654.GA25171@redhat.com> References: <20090819173654.GA25171@redhat.com> Message-ID: <20090820182149.GA26316@redhat.com> On 08/19, Oleg Nesterov wrote: > > @@ -471,35 +471,45 @@ static int ptrace_attach_task(struct tas > { > + if (likely(!tracee->ptrace)) { I forgot about UTRACE_DETACH in case tracee->ptrace != 0, updated patch below. ------------------------------------------------------------------------------- [PATCH 09] move ->ptrace == 0 checks to ptrace_attach_task() Until we kill ->ptrace, attach must ensure ->ptrace == 0 to avoid the races with detach. We can move these checks to ptrace_attach_task() from the callers, and we can do this check lockless. >From now ptrace_abort_attach() is only called when the tracee had no chance to execute any callback, a simple UTRACE_DETACH is enough. ptrace_attach() doesn't need ptrace_abort_attach() at all, if the tracee is killed we don't care about attached engine. --- kernel/ptrace.c | 67 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 31 deletions(-) --- PU/kernel/ptrace.c~09_MV_PTRACE_CK 2009-08-19 16:49:25.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-20 20:04:59.000000000 +0200 @@ -471,35 +471,47 @@ static int ptrace_attach_task(struct tas { struct utrace_engine *engine; unsigned long events; + int err = -EPERM; engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, &ptrace_utrace_ops, NULL); if (unlikely(IS_ERR(engine))) { - int err = PTR_ERR(engine); - if (err != -ESRCH && err != -ERESTARTNOINTR) - err = -EPERM ; + if (PTR_ERR(engine) == -ESRCH || + PTR_ERR(engine) == -ERESTARTNOINTR) + err = PTR_ERR(engine); return err; } + /* - * We need QUIESCE for resume handling, CLONE to check - * for CLONE_PTRACE, other events are always reported. - */ - events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | - UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; - /* - * It can fail only if the tracee is dead, the caller - * must notice this before setting PT_PTRACED. + * Check ->ptrace to make sure we don't race with the previous + * tracer which didn't finish detach. If it is clear, nobody + * can change it except us due to UTRACE_ATTACH_EXCLUSIVE. */ - utrace_set_events(tracee, engine, events); + if (unlikely(tracee->ptrace)) { + utrace_control(tracee, engine, UTRACE_DETACH); + } else { + /* + * We need QUIESCE for resume handling, CLONE to check + * for CLONE_PTRACE, other events are always reported. + */ + events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | + UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; + /* + * It can fail only if the tracee is dead, the caller + * must notice this before setting PT_PTRACED. + */ + utrace_set_events(tracee, engine, events); + err = 0; + } + utrace_engine_put(engine); - return 0; + return err; } static void ptrace_abort_attach(struct task_struct *tracee) { - /* XXX we raced with detach. Double check UTRACE_DETACH is enough */ ptrace_detach_task(tracee, 0); } @@ -613,9 +625,8 @@ int ptrace_attach(struct task_struct *ta retval = -EPERM; if (unlikely(task->exit_state)) goto unlock_tasklist; - if (task->ptrace) - goto unlock_tasklist; + BUG_ON(task->ptrace); task->ptrace = PT_PTRACED; if (capable(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; @@ -626,8 +637,6 @@ int ptrace_attach(struct task_struct *ta retval = 0; unlock_tasklist: write_unlock_irq(&tasklist_lock); - if (retval) - ptrace_abort_attach(task); unlock_creds: mutex_unlock(&task->cred_guard_mutex); out: @@ -650,19 +659,17 @@ int ptrace_traceme(void) ret = -EPERM; write_lock_irq(&tasklist_lock); - /* Are we already being traced? */ - if (!current->ptrace) { - ret = security_ptrace_traceme(current->parent); - /* - * Check PF_EXITING to ensure ->real_parent has not passed - * exit_ptrace(). Otherwise we don't report the error but - * pretend ->real_parent untraces us right after return. - */ - if (!ret && !(current->real_parent->flags & PF_EXITING)) { - current->ptrace = PT_PTRACED; - __ptrace_link(current, current->real_parent); - detach = false; - } + BUG_ON(current->ptrace); + ret = security_ptrace_traceme(current->parent); + /* + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. + */ + if (!ret && !(current->real_parent->flags & PF_EXITING)) { + current->ptrace = PT_PTRACED; + __ptrace_link(current, current->real_parent); + detach = false; } write_unlock_irq(&tasklist_lock); From oleg at redhat.com Thu Aug 20 18:48:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 20 Aug 2009 20:48:53 +0200 Subject: [PATCH] utrace: utrace_finish_vfork: check ->vfork_stop lockless In-Reply-To: <20090819181851.GA26313@redhat.com> References: <20090819180128.GA26296@redhat.com> <20090819181851.GA26313@redhat.com> Message-ID: <20090820184853.GB26316@redhat.com> On 08/19, Oleg Nesterov wrote: > > I hope I missed something, but I'm _afraid_ we may have problems. > > Looks like we can almost never use utrace->xxx:1 fields without ->lock. > Suppose that, for example, utrace_control(UTRACE_REPORT) does > > utrace->report = 1; > > But report/interrupt/etc are all bitfields :1. Doesn't this mean compiler > can do anything it wants with the word where these bitfields live? Can't > it temporary (say) clear ->interrupt while setting ->report ? > > IOW, as a perl programmer I need your help with "C". Do we have any > guarantee that compiler will always update the word "as a whole" ? OK, I think this was a false alarm. But I failed to google the "proof". Oleg. From oleg at redhat.com Thu Aug 20 19:42:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 20 Aug 2009 21:42:51 +0200 Subject: utrace_stop() && UTRACE_DETACH Message-ID: <20090820194251.GA29913@redhat.com> In short: how can the tracer do UTRACE_DETACH and make sure it doesn't leave the tracee in TASK_TRACED state? My concern is ptrace, but I think thw question is about utrace in general. There is no way to "cancel" utrace_stop() if it didn't take utrace->lock yet. ptrace(PTRACE_DETACH) is easy. The tracee is stopped or killed. But what about the implicit detach from exit_ptrace() ? Suppose the tracer calls utrace_control(UTRACE_DETACH) right before the tracee calls utrace_stop(). What can we do then? The tracer can't know the tracee is going to stop, the tracee can't know it should not stop. (I am ignoring the case when there are other tracers). If the tracer calls utrace_barrier() after UTRACE_DETACH, it will spin until the TASK_TRACED tracee is killed, get_utrace_lock() will notice utrace_detached_ops and return -ERESTARTSYS. It seems to me utrace.c needs some changes to help, no? Looks like, utrace_stop() should re-check engines after spin_lock() and do something similar to what utrace_reset() reset does. Also. I think this re-check should look again at engine_wants_stop(), this can help to avoid the races with utrace_wakeup(). IOW, how about something like static bool utrace_stop_trylock(...) { bool should_stop; again; spin_lock(&utrace->lock); should_stop = false; list_for_each_entry_safe(engine, next, &utrace->attached, entry) { if (engine->ops == &utrace_detached_ops) { utrace_reset(); goto again; } should_stop ||= engine_wants_stop(engine); } if (!should_stop) spin_unlock(&utrace->lock); return should_stop; } Then, utrace_stop() is changed - spin_lock(&utrace->lock); + if (!utrace_stop_trylock(...)) + return; Thoughts? (I don't really think utrace_stop_trylock() (the name is random) should actually call utrace_reset(), just to explain what I mean). Oleg. From hot-deals at clubvacationdeals.com Fri Aug 21 02:40:32 2009 From: hot-deals at clubvacationdeals.com (Club Vacation Deals) Date: Thu, 20 Aug 2009 22:40:32 -0400 Subject: Cancun or Vallarta vacation 30 usd Message-ID: <0c245cf042d9c62d3dc160b6eb73d7fa@www.vallarta-paradise.com> An HTML attachment was scrubbed... URL: From srikar at linux.vnet.ibm.com Fri Aug 21 08:05:41 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Fri, 21 Aug 2009 13:35:41 +0530 Subject: [PATCH 09] move ->ptrace == 0 checks to ptrace_attach_task() In-Reply-To: <20090820182149.GA26316@redhat.com> References: <20090819173654.GA25171@redhat.com> <20090820182149.GA26316@redhat.com> Message-ID: <20090821080541.GA16899@linux.vnet.ibm.com> Hi Oleg, > > --- PU/kernel/ptrace.c~09_MV_PTRACE_CK 2009-08-19 16:49:25.000000000 +0200 > +++ PU/kernel/ptrace.c 2009-08-20 20:04:59.000000000 +0200 > @@ -471,35 +471,47 @@ static int ptrace_attach_task(struct tas > { > struct utrace_engine *engine; > unsigned long events; > + int err = -EPERM; > > engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | > UTRACE_ATTACH_EXCLUSIVE | > UTRACE_ATTACH_MATCH_OPS, > &ptrace_utrace_ops, NULL); > if (unlikely(IS_ERR(engine))) { > - int err = PTR_ERR(engine); > - if (err != -ESRCH && err != -ERESTARTNOINTR) > - err = -EPERM ; > + if (PTR_ERR(engine) == -ESRCH || > + PTR_ERR(engine) == -ERESTARTNOINTR) > + err = PTR_ERR(engine); > return err; > } > + > /* > - * We need QUIESCE for resume handling, CLONE to check > - * for CLONE_PTRACE, other events are always reported. > - */ > - events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | > - UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; > - /* > - * It can fail only if the tracee is dead, the caller > - * must notice this before setting PT_PTRACED. > + * Check ->ptrace to make sure we don't race with the previous > + * tracer which didn't finish detach. If it is clear, nobody > + * can change it except us due to UTRACE_ATTACH_EXCLUSIVE. > */ > - utrace_set_events(tracee, engine, events); > + if (unlikely(tracee->ptrace)) { Any reason why we cant move this check before we do utrace_attach_task? > + utrace_control(tracee, engine, UTRACE_DETACH); -- Thanks and Regards Srikar From oleg at redhat.com Fri Aug 21 09:40:03 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 21 Aug 2009 11:40:03 +0200 Subject: [PATCH 09] move ->ptrace == 0 checks to ptrace_attach_task() In-Reply-To: <20090821080541.GA16899@linux.vnet.ibm.com> References: <20090819173654.GA25171@redhat.com> <20090820182149.GA26316@redhat.com> <20090821080541.GA16899@linux.vnet.ibm.com> Message-ID: <20090821094003.GA32376@redhat.com> Hi Srikar, On 08/21, Srikar Dronamraju wrote: > > > > --- PU/kernel/ptrace.c~09_MV_PTRACE_CK 2009-08-19 16:49:25.000000000 +0200 > > +++ PU/kernel/ptrace.c 2009-08-20 20:04:59.000000000 +0200 > > @@ -471,35 +471,47 @@ static int ptrace_attach_task(struct tas > > { > > struct utrace_engine *engine; > > unsigned long events; > > + int err = -EPERM; > > > > engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | > > UTRACE_ATTACH_EXCLUSIVE | > > UTRACE_ATTACH_MATCH_OPS, > > &ptrace_utrace_ops, NULL); > > if (unlikely(IS_ERR(engine))) { > > - int err = PTR_ERR(engine); > > - if (err != -ESRCH && err != -ERESTARTNOINTR) > > - err = -EPERM ; > > + if (PTR_ERR(engine) == -ESRCH || > > + PTR_ERR(engine) == -ERESTARTNOINTR) > > + err = PTR_ERR(engine); > > return err; > > } > > + > > /* > > - * We need QUIESCE for resume handling, CLONE to check > > - * for CLONE_PTRACE, other events are always reported. > > - */ > > - events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | > > - UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; > > - /* > > - * It can fail only if the tracee is dead, the caller > > - * must notice this before setting PT_PTRACED. > > + * Check ->ptrace to make sure we don't race with the previous > > + * tracer which didn't finish detach. If it is clear, nobody > > + * can change it except us due to UTRACE_ATTACH_EXCLUSIVE. > > */ > > - utrace_set_events(tracee, engine, events); > > > > + if (unlikely(tracee->ptrace)) { > > Any reason why we cant move this check before we do utrace_attach_task? Please note the comment, this check relies on UTRACE_ATTACH_EXCLUSIVE above. Once we see ->ptrace = 0 after utrace_attach_task(), nobody can change ->ptrace. Now suppose ptrace_attach_task() does if (tracee->ptrace) return; /* --- WINDOW --- */ engine = utrace_attach_task(); if (IS_ERR(engine)) return; ...complete attach... In that WINDOW, another tracer can attach to this tracee, then start the detach and remove the engine, but do not call __ptrace_unlink() yet. Oleg. From srikar at linux.vnet.ibm.com Fri Aug 21 13:02:08 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Fri, 21 Aug 2009 18:32:08 +0530 Subject: [PATCH 09] move ->ptrace == 0 checks to ptrace_attach_task() In-Reply-To: <20090821094003.GA32376@redhat.com> References: <20090819173654.GA25171@redhat.com> <20090820182149.GA26316@redhat.com> <20090821080541.GA16899@linux.vnet.ibm.com> <20090821094003.GA32376@redhat.com> Message-ID: <20090821130208.GA28420@linux.vnet.ibm.com> Hi Oleg, Thanks for the clarification. > > Please note the comment, this check relies on UTRACE_ATTACH_EXCLUSIVE > above. Once we see ->ptrace = 0 after utrace_attach_task(), nobody > can change ->ptrace. However after attaching an engine exclusively, (which would mean the child is not traced or was detached, or is about to be detached,) we may still find ->ptrace to be non-NULL and detach the engine. Currently we do ptrace_detach_task() just before __ptrace_unlink(). Is there any specific reason to do ptrace_detach_task() before __ptrace_unlink()? Is it possible to have ptrace_detach_task() which is not immediately followed by __ptrace_unlink()? If there is no such possibility then can we do ptrace_detach_task() after __ptrace_unlink(). This could mean attaching an engine with UTRACE_ATTACH_EXCLUSIVE flag set is enough to say ->ptrace = 0 -- Thanks and Regards Srikar From oleg at redhat.com Fri Aug 21 14:05:13 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 21 Aug 2009 16:05:13 +0200 Subject: [PATCH 09] move ->ptrace == 0 checks to ptrace_attach_task() In-Reply-To: <20090821130208.GA28420@linux.vnet.ibm.com> References: <20090819173654.GA25171@redhat.com> <20090820182149.GA26316@redhat.com> <20090821080541.GA16899@linux.vnet.ibm.com> <20090821094003.GA32376@redhat.com> <20090821130208.GA28420@linux.vnet.ibm.com> Message-ID: <20090821140513.GA11451@redhat.com> On 08/21, Srikar Dronamraju wrote: > > > Please note the comment, this check relies on UTRACE_ATTACH_EXCLUSIVE > > above. Once we see ->ptrace = 0 after utrace_attach_task(), nobody > > can change ->ptrace. > > However after attaching an engine exclusively, (which would mean the > child is not traced or was detached, or is about to be detached,) > we may still find ->ptrace to be non-NULL and detach the engine. > > Currently we do ptrace_detach_task() just before __ptrace_unlink(). Is > there any specific reason to do ptrace_detach_task() before > __ptrace_unlink()? Is it possible to have ptrace_detach_task() > which is not immediately followed by __ptrace_unlink()? > > If there is no such possibility then can we do ptrace_detach_task() > after __ptrace_unlink(). This could mean attaching an engine with > UTRACE_ATTACH_EXCLUSIVE flag set is enough to say ->ptrace = 0 Yes, and I thought about this. And please note that this patch makes sense anyway: if we change the order of detach (or when we finally kill task_struct->ptrace), we can just remove this single check in ptrace_attach_task(). In fact this was one of the reasons to make this patch. But. I am not sure yet detach can always __ptrace_unlink() first, and for the first version I am not going to do this change without strong reasons. Oleg. From webmaster at hallmark.org Sat Aug 22 09:42:19 2009 From: webmaster at hallmark.org (webmaster at hallmark.org) Date: Sat, 22 Aug 2009 04:42:19 -0500 (EST) Subject: You have received a card from a family member! Message-ID: <20090822094829.081D48490FF@mail.glgwebservice.com> An HTML attachment was scrubbed... URL: From asphalt5newcomer at yahoo.com Sat Aug 22 10:08:43 2009 From: asphalt5newcomer at yahoo.com (Octavio E Salinas) Date: Sat, 22 Aug 2009 14:08:43 +0400 Subject: Email Directory of small companies in the States Message-ID: Fields like website, emails address, postal address phone, fax and more 2 million emails in total, sorted by state Introductory special price for this week only: $295 - If you order by this Friday send email to: Major at BestAccurateReliable.com email exit at BestAccurateReliable.com for delisting From oleg at redhat.com Sat Aug 22 18:58:33 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 22 Aug 2009 20:58:33 +0200 Subject: [PATCH 11] ptrace_detach: kill the unconditional wakeup Message-ID: <20090822185833.GA31670@redhat.com> I do not know what to do with ptrace_detach()->wake_up_process(). It is wrong even without utrace. But it is doubly wrong with utrace. So I am re-sending 95a3540da9c81a5987be810e1d9a83640a366bd5 --- kernel/ptrace.c | 2 -- 1 file changed, 2 deletions(-) --- PU/kernel/ptrace.c~11_DETACH_KILL_WAKE 2009-08-22 19:17:00.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-22 20:06:42.000000000 +0200 @@ -757,8 +757,6 @@ int ptrace_detach(struct task_struct *ch if (child->ptrace) { child->exit_code = data; dead = __ptrace_detach(current, child); - if (!child->exit_state) - wake_up_process(child); } write_unlock_irq(&tasklist_lock); From oleg at redhat.com Sat Aug 22 18:58:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 22 Aug 2009 20:58:36 +0200 Subject: [PATCH 12] ptrace_detach: do ptrace_unlink() first Message-ID: <20090822185836.GA31674@redhat.com> Currently ptrace_detach does UTRACE_DETACH then ptrace_unlink(). This is not right, UTRACE_DETACH wakes up the tracee. It can stop/die after that, but since it is still task_ptrace() this can confuse its ->real_parent. We can't solve this if we add __wake_up_parent(->real_parent). So change the order. And move most of the code into the new helper, ptrace_do_detach(). It will be use by exit_ptrace(). --- kernel/ptrace.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) --- PU/kernel/ptrace.c~12_REWORK_DETACH 2009-08-22 20:06:42.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-22 20:08:23.000000000 +0200 @@ -740,28 +740,38 @@ static bool __ptrace_detach(struct task_ return false; } -int ptrace_detach(struct task_struct *child, unsigned int data) +static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) { - bool dead = false; - - if (!valid_signal(data)) - return -EIO; - - ptrace_detach_task(child, data); + bool traced, dead; write_lock_irq(&tasklist_lock); /* - * This child can be already killed. Make sure de_thread() or + * This tracee can be already killed. Make sure de_thread() or * our sub-thread doing do_wait() didn't do release_task() yet. */ - if (child->ptrace) { - child->exit_code = data; - dead = __ptrace_detach(current, child); + traced = tracee->ptrace; + if (likely(traced)) { + tracee->exit_code = data; + dead = __ptrace_detach(current, tracee); } write_unlock_irq(&tasklist_lock); - if (unlikely(dead)) - release_task(child); + if (unlikely(!traced)) + return; + if (unlikely(dead)) { + release_task(tracee); + return; + } + + ptrace_detach_task(tracee, data); +} + +int ptrace_detach(struct task_struct *child, unsigned int data) +{ + if (!valid_signal(data)) + return -EIO; + + ptrace_do_detach(child, data); return 0; } From oleg at redhat.com Sat Aug 22 18:58:38 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 22 Aug 2009 20:58:38 +0200 Subject: [PATCH 13] exit_ptrace: use ptrace_do_detach() Message-ID: <20090822185838.GA31681@redhat.com> Change exit_ptrace() to use ptrace_do_detach() and kill now unused ptrace_utrace_exit(). This means we can't iterate over ->ptraced (the current code does this twice) under tasklist, change the code to pick tracees by one and do get/put on task_struct. With this patch, exit_ptrace() does ptrace_unlink() then UTRACE_DETACH. But currently this is not exactly correct too. Unlike ptrace_detach(), exit_ptrace() can be called when the tracee is running, if it calls utrace_stop() before UTRACE_DETACH we will notify ->real_parent. Hopefully this will be fixed when we change the ptrace-related kludge in utrace_stop(). --- kernel/ptrace.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) --- PU/kernel/ptrace.c~13_REWORK_EXIT_PTRACE 2009-08-22 20:08:23.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-22 20:31:26.000000000 +0200 @@ -751,7 +751,8 @@ static void ptrace_do_detach(struct task */ traced = tracee->ptrace; if (likely(traced)) { - tracee->exit_code = data; + if (valid_signal(data)) + tracee->exit_code = data; dead = __ptrace_detach(current, tracee); } write_unlock_irq(&tasklist_lock); @@ -776,37 +777,26 @@ int ptrace_detach(struct task_struct *ch return 0; } -static void ptrace_utrace_exit(struct task_struct *task) -{ - struct task_struct *child; - read_lock(&tasklist_lock); - list_for_each_entry(child, &task->ptraced, ptrace_entry) - ptrace_detach_task(child, 0); - read_unlock(&tasklist_lock); -} - /* * Detach all tasks we were using ptrace on. */ void exit_ptrace(struct task_struct *tracer) { - struct task_struct *p, *n; - LIST_HEAD(ptrace_dead); - - ptrace_utrace_exit(tracer); - - write_lock_irq(&tasklist_lock); - list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) { - if (__ptrace_detach(tracer, p)) - list_add(&p->ptrace_entry, &ptrace_dead); - } - write_unlock_irq(&tasklist_lock); + for (;;) { + struct task_struct *tracee = NULL; - BUG_ON(!list_empty(&tracer->ptraced)); + read_lock(&tasklist_lock); + if (!list_empty(&tracer->ptraced)) { + tracee = list_first_entry(&tracer->ptraced, + struct task_struct, ptrace_entry); + get_task_struct(tracee); + } + read_unlock(&tasklist_lock); + if (!tracee) + break; - list_for_each_entry_safe(p, n, &ptrace_dead, ptrace_entry) { - list_del_init(&p->ptrace_entry); - release_task(p); + ptrace_do_detach(tracee, -1); + put_task_struct(tracee); } } From oleg at redhat.com Sat Aug 22 18:58:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 22 Aug 2009 20:58:41 +0200 Subject: [PATCH 14] ptrace_attach_task: kill ->ptrace != 0 check Message-ID: <20090822185841.GA31684@redhat.com> Now we can kill ->ptrace check in ptrace_attach_task(), if the task is not dead we always clear ->ptrace before UTRACE_DETACH. This reverts most part of "[PATCH 09] move ->ptrace == 0 checks to ptrace_attach_task()", but I am just sending the new patch on top of previous changes to avoid the confusion. --- kernel/ptrace.c | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) --- PU/kernel/ptrace.c~14_ATTACH_DONT_CK_PTRACE 2009-08-22 20:31:26.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-22 20:46:41.000000000 +0200 @@ -485,43 +485,30 @@ static int ptrace_attach_task(struct tas { struct utrace_engine *engine; unsigned long events; - int err = -EPERM; engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, &ptrace_utrace_ops, NULL); if (unlikely(IS_ERR(engine))) { - if (PTR_ERR(engine) == -ESRCH || - PTR_ERR(engine) == -ERESTARTNOINTR) - err = PTR_ERR(engine); + int err = PTR_ERR(engine); + if (err != -ESRCH && err != -ERESTARTNOINTR) + err = -EPERM ; return err; } - /* - * Check ->ptrace to make sure we don't race with the previous - * tracer which didn't finish detach. If it is clear, nobody - * can change it except us due to UTRACE_ATTACH_EXCLUSIVE. + * We need QUIESCE for resume handling, CLONE to check + * for CLONE_PTRACE, other events are always reported. */ - if (unlikely(tracee->ptrace)) { - utrace_control(tracee, engine, UTRACE_DETACH); - } else { - /* - * We need QUIESCE for resume handling, CLONE to check - * for CLONE_PTRACE, other events are always reported. - */ - events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | - UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; - /* - * It can fail only if the tracee is dead, the caller - * must notice this before setting PT_PTRACED. - */ - utrace_set_events(tracee, engine, events); - err = 0; - } - + events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | + UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; + /* + * It can fail only if the tracee is dead, the caller + * must notice this before setting PT_PTRACED. + */ + utrace_set_events(tracee, engine, events); utrace_engine_put(engine); - return err; + return 0; } static void ptrace_abort_attach(struct task_struct *tracee) From oleg at redhat.com Sat Aug 22 21:33:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 22 Aug 2009 23:33:10 +0200 Subject: [PATCH 09] move ->ptrace == 0 checks to ptrace_attach_task() In-Reply-To: <20090821140513.GA11451@redhat.com> References: <20090819173654.GA25171@redhat.com> <20090820182149.GA26316@redhat.com> <20090821080541.GA16899@linux.vnet.ibm.com> <20090821094003.GA32376@redhat.com> <20090821130208.GA28420@linux.vnet.ibm.com> <20090821140513.GA11451@redhat.com> Message-ID: <20090822213310.GA4549@redhat.com> On 08/21, Oleg Nesterov wrote: > > On 08/21, Srikar Dronamraju wrote: > > > > > Please note the comment, this check relies on UTRACE_ATTACH_EXCLUSIVE > > > above. Once we see ->ptrace = 0 after utrace_attach_task(), nobody > > > can change ->ptrace. > > > > However after attaching an engine exclusively, (which would mean the > > child is not traced or was detached, or is about to be detached,) > > we may still find ->ptrace to be non-NULL and detach the engine. Missed this part... Yes, but I think this is OK. If we find ->ptrace != 0 we can fail. The child is about to be detached, but it is still traced or we can pretend it was traced when we called attach. > > Currently we do ptrace_detach_task() just before __ptrace_unlink(). Is > > there any specific reason to do ptrace_detach_task() before > > __ptrace_unlink()? Is it possible to have ptrace_detach_task() > > which is not immediately followed by __ptrace_unlink()? > > > > If there is no such possibility then can we do ptrace_detach_task() > > after __ptrace_unlink(). This could mean attaching an engine with > > UTRACE_ATTACH_EXCLUSIVE flag set is enough to say ->ptrace = 0 > > Yes, and I thought about this. And please note that this patch makes > sense anyway: if we change the order of detach (or when we finally kill > task_struct->ptrace), we can just remove this single check in > ptrace_attach_task(). In fact this was one of the reasons to make this > patch. > > But. I am not sure yet detach can always __ptrace_unlink() first, and > for the first version I am not going to do this change without strong > reasons. And we seem to have strong reasons. Srikar, sorry I forgot to CC you. Hopefully you can read utrace-devel. Oleg. From pnuwagaba at tupperware.com Sun Aug 23 04:34:13 2009 From: pnuwagaba at tupperware.com (Madeleine Numbers) Date: Sun, 23 Aug 2009 05:34:13 +0100 Subject: Get the pilules from a pharmacy that believes in providing excellent services and worlwide shipping! Message-ID: <000a01ca23a2$9577c910$793eb2ba@cw5ssvcm62dxs0sxaz> This is wonderful that you can have perfect intimate life now. http://ef.smellrose.com/ From oleg at redhat.com Sun Aug 23 17:09:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 23 Aug 2009 19:09:54 +0200 Subject: Q: signals: UTRACE_SIGNAL_HANDLER, multitracing Message-ID: <20090823170954.GA20110@redhat.com> Trying to understand what ptrace_report_signal() should do, a couple of questions... Why does utrace_signal_handler() set ->signal_handler when !stepping? If I understand correctly, the logic is if (stepping) make sure that before return to user-space UTRACE_SIGNAL_HANDLER will be reported. This is understandable. More or less. else make sure that UTRACE_SIGNAL_REPORT is not possible before we return to user-space, UTRACE_SIGNAL_HANDLER should be used instead. Why? I mean, why this is useful? Another question. How can ->report_signal(info) change info->si_signo (or other data in *info) when we have multiple engines? I mean, how can engines cooperate if they want to change ->si_signo. For example, ptrace_report_signal() sets ->si_signo = SIGTRAP. But if we have another engine attached before ptrace-engine, then its ->report_signal() was already called. This means that engine can't know about this SIGTRAP? In short. If any engine changes *info, how should it take into account other engines attached before? ptrace also changes *info via ->last_siginfo. IOW, the owner of engine plays with info, not ->report_signal(). I assume that ptrace is the only engine which "has rights" to play with *info outside of ->report_signal(), right? Oleg. From roland at redhat.com Mon Aug 24 06:32:18 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 23 Aug 2009 23:32:18 -0700 (PDT) Subject: [PATCH 07] rework prepare_ptrace_attach/finish_ptrace_attach In-Reply-To: Oleg Nesterov's message of Wednesday, 19 August 2009 14:33:18 +0200 <20090819123318.GA632@redhat.com> References: <20090817152258.GA10674@redhat.com> <20090818001522.206234730F@magilla.sf.frob.com> <20090818164400.GA13635@redhat.com> <20090818222527.6F5134730F@magilla.sf.frob.com> <20090819123318.GA632@redhat.com> Message-ID: <20090824063218.9B664414DF@magilla.sf.frob.com> > > I don't really understand why the SIGSTOP is your concern. > > No matter what, you send that last, after ptrace is wired up to catch it. > > Because the tracee must not dequeue and handle this SIGSTOP until it sees > UTRACE_EVENT_SIGNAL_ALL in ->utrace_flags. Right. utrace_set_events() sets ->utrace_flags while holding utrace->lock. Then send_sig() queues the signal while holding siglock. Are the barriers implicit in those locks not enough to guarantee that ->utrace_flags updates are done by the time siglock is released, in the view of the other CPU that then acquires siglock before reading ->utrace_flags (tracehook_get_signal)? > Yes, ->ptrace should die. But we can't kill it right now. (I mean, I don't > see how can we kill it before we have a more or less working ptrace code). Ok. > Until we kill it, ptrace_attach pathes should > > - set PT_PTRACED for task_ptrace() callers in exit/signal/etc.c You mean the wait and do_notify_parent* paths. Ok, it needs something outside utrace proper as the mark for these, and it might as well remain this for now. > - check it to avoid the races with another tracer doing detach, > iow simply to prevent __ptrace_link() before __ptrace_unlink(). I remain skeptical that this is a clean way to do things in the long run. But ok. Thanks, Roland From roland at redhat.com Mon Aug 24 06:47:36 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 23 Aug 2009 23:47:36 -0700 (PDT) Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: Oleg Nesterov's message of Wednesday, 19 August 2009 15:53:23 +0200 <20090819135323.GC632@redhat.com> References: <20090814144555.GA28295@redhat.com> <20090818045433.511254730F@magilla.sf.frob.com> <20090818181732.GA17634@redhat.com> <20090818211627.6F0274730F@magilla.sf.frob.com> <20090819135323.GC632@redhat.com> Message-ID: <20090824064736.2F3D7414DF@magilla.sf.frob.com> > > This model seems like a better fit for ptrace to me. The anchoring data > > structure is the tracer's tracees list, which links together the > > ptrace_context structs. A live ptrace_context has an engine pointer and > > a ref for it. > > OK. Not that I really understand this all in details, but OK. > > But. Do you think we should do this right now? If it is the right way to handle the data structure lifetimes, I don't see why we would do it any different way first. One of the main points of what makes one plan or another "the right way" is that it makes it easier to get the corners right. So if it's easier to get the corners right another way, then maybe that other way is the right one. > I don't. Imho, we need a lot of changes before this. I don't understand why you think this. > We need the working code first. I just can't understand how can we do the > necessary changes to solve (say) the problems with de_thread() now, when > it is not clear (to me) how the basic/core ptrace code will look. This subject is part of how we organize the basic/core ptrace data structures. I don't think we have to make things like the MT exec case perfect right away. In fact, I think that wrinkle is the only thing that makes the "hold another ref" model I described not completely simple and straightforward to apply. > Do you have any suggestion what can we do right now? (assuming you won't > apply your ops->release patch). I didn't say I wouldn't. I was hoping for some more discussion about it and better understanding of the underlying issues that made you want it, maybe with some voices other than just yours and mine. I'm having trouble understanding why you think I've suggested some new tangent of work bigger or different from what you're already engaged in. So I'm at a bit of a loss for what different thing you're hoping I can suggest. > > I don't really follow this at all. > > Your ptrace code has nothing to do with utrace->lock, and never will. > > Yes, agreed. ptrace should not use utrace->lock. But currently I don't > see how to do this without utrace->lock. Or without rcu + refcnt. Sorry, but I still really have no idea what you are thinking about here. If you are considering overloading this unrelated lock for some purpose, you'll have to explain how you want to use it and why that's necessary. Thanks, Roland From roland at redhat.com Mon Aug 24 07:03:37 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 24 Aug 2009 00:03:37 -0700 (PDT) Subject: [PATCH 11] ptrace_detach: kill the unconditional wakeup In-Reply-To: Oleg Nesterov's message of Saturday, 22 August 2009 20:58:33 +0200 <20090822185833.GA31670@redhat.com> References: <20090822185833.GA31670@redhat.com> Message-ID: <20090824070338.036F1414DF@magilla.sf.frob.com> > I do not know what to do with ptrace_detach()->wake_up_process(). It and ptrace_resume()->wake_up_process() are both clearly wrong in general. I think all we really need to worry about is making sure that the ptrace-tests suite has tests that express all the assumptions and requirements of existing applications (i.e. old gdb versions). If those are inherently contradictory then we can work out the right compromises and get the suite to test "as compatible as we want it" manifest ptrace behavior. Then as long as we don't regress there, our kernel changes are OK. I think the mayhem of poor bookkeeping might make it too much hassle to try to fix the existing upstream code to use the proper conditional wake-ups. It's not worth putting time into it if that's so. Thanks, Roland From roland at redhat.com Mon Aug 24 07:53:25 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 24 Aug 2009 00:53:25 -0700 (PDT) Subject: Q: signals: UTRACE_SIGNAL_HANDLER, multitracing In-Reply-To: Oleg Nesterov's message of Sunday, 23 August 2009 19:09:54 +0200 <20090823170954.GA20110@redhat.com> References: <20090823170954.GA20110@redhat.com> Message-ID: <20090824075325.69EDC414DF@magilla.sf.frob.com> > Why does utrace_signal_handler() set ->signal_handler when !stepping? > > If I understand correctly, the logic is > > if (stepping) > make sure that before return to user-space > UTRACE_SIGNAL_HANDLER will be reported. > > This is understandable. More or less. > else > make sure that UTRACE_SIGNAL_REPORT is not > possible before we return to user-space, > UTRACE_SIGNAL_HANDLER should be used instead. > > Why? I mean, why this is useful? If you want to let a signal happen and then see the new user state before letting user-mode run, then you'd: return UTRACE_SIGNAL_DELIVER|UTRACE_REPORT; or: return UTRACE_SIGNAL_DELIVER|UTRACE_INTERRUPT; IMHO this is the more natural way to express what you want than UTRACE_SINGLESTEP. It's also possible and kosher to do this on a machine where UTRACE_SINGLESTEP is not supported. The main reason that single-step has this behavior implicitly is for the benefit of ptrace. That is, the traditional behavior is to pretend there was a SIGTRAP at handler setup when stepping, i.e. as if "deliver signal" were an instruction and you'd just stepped over it to get to the first instruction of the handler. The UTRACE_SIGNAL_DELIVER logic for handled signals should already mean that utrace->interrupt is forced even for UTRACE_REPORT. So it might be fine for utrace_signal_handler() to set ->signal_handler only if ->interrupt is already set. So maybe this? (I haven't committed this.) Thanks, Roland diff --git a/kernel/utrace.c b/kernel/utrace.c index 2e63a11..70d032f 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -2174,11 +2174,12 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, } /* - * This gets called after a signal handler has been set up. - * We set a flag so the next report knows it happened. - * If we're already stepping, make sure we do a report_signal. - * If not, make sure we get into utrace_resume() where we can - * clear the signal_handler flag before resuming. + * This gets called after a signal handler has been set up. If someone + * wanted a UTRACE_SIGNAL_HANDLER report_signal in particular, then + * utrace->interrupt is already set and we set the signal_handler flag + * so the next report knows it happened. If not, keep the flag clear so + * that we do not have to come back and reset it before resume just for + * bookkeeping purposes. */ void utrace_signal_handler(struct task_struct *task, int stepping) { @@ -2186,13 +2187,7 @@ void utrace_signal_handler(struct task_struct *task, int stepping) spin_lock(&utrace->lock); - utrace->signal_handler = 1; - if (stepping) { - utrace->interrupt = 1; - set_tsk_thread_flag(task, TIF_SIGPENDING); - } else { - set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); - } + utrace->signal_handler = utrace->interrupt; spin_unlock(&utrace->lock); } From roland at redhat.com Mon Aug 24 08:21:54 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 24 Aug 2009 01:21:54 -0700 (PDT) Subject: Q: signals: UTRACE_SIGNAL_HANDLER, multitracing In-Reply-To: Oleg Nesterov's message of Sunday, 23 August 2009 19:09:54 +0200 <20090823170954.GA20110@redhat.com> References: <20090823170954.GA20110@redhat.com> Message-ID: <20090824082154.886EA414DF@magilla.sf.frob.com> > Another question. How can ->report_signal(info) change info->si_signo > (or other data in *info) when we have multiple engines? I mean, how > can engines cooperate if they want to change ->si_signo. This is just an instance of the general subject of engine cooperation when engines do perturbation. Each engine's report_signal callback gets arguments saying what the previous engine decided to do. This includes the enum utrace_signal_action, the siginfo_t contents, and the sigaction--as well as all of the user registers and memory. Each engine can change any of those how it sees fit. > For example, ptrace_report_signal() sets ->si_signo = SIGTRAP. But > if we have another engine attached before ptrace-engine, then its > ->report_signal() was already called. This means that engine can't > know about this SIGTRAP? Well, there wasn't any SIGTRAP. That engine doesn't know about the virtual reality that the ptrace engine is creating. In the same way, if that engine A precedes an engine C whose report_quiesce(0) changes the user registers, then A will never know that user-mode ran with different register contents than what its report_quiesce(0) observed. That's just the fundamental nature of there being an ordering among engines. Similarly, if engine C follows the ptrace engine, it will perceive(*) that there was a SIGTRAP that the ptrace engine then decided to ignore. *unless it checks the orig_ka argument, which is NULL to indicate that there this is a UTRACE_SIGNAL_{REPORT,HANDLER} pass without an original real signal. > In short. If any engine changes *info, how should it take into account > other engines attached before? If you are perturbing the state, then you've decided you don't really care about what came before. An engine like ptrace is not really trying to keep out of the way of other engines, it's just doing what it does. The intent of the API is that every engine has the opportunity to be informed about what other engines are doing, and make its own decisions. The fact of ordering and the linear nature of time means that each engine can't really be aware of every other engine all the time, only the earlier ones in the list (and indirectly see the effects of later ones after the fact through means like UTRACE_REPORT). > ptrace also changes *info via ->last_siginfo. IOW, the owner of engine > plays with info, not ->report_signal(). I assume that ptrace is the only > engine which "has rights" to play with *info outside of ->report_signal(), > right? Well, it certainly doesn't seem like all that clean a thing to do. But the kerneldoc for the report_signal API does document: For a report without a new signal, @info * is left uninitialized and must be set completely by an engine that * chooses to deliver a signal; if there was a previous @report_signal * callback ending in %UTRACE_STOP and it was just resumed using * %UTRACE_REPORT or %UTRACE_INTERRUPT, then @info is left unchanged * from the previous callback. In this way, the original signal can * be left in @info while returning %UTRACE_STOP|%UTRACE_SIGNAL_IGN * and then found again when resuming @task with %UTRACE_INTERRUPT. So I think the bottom line is that this is something that you can fiddle with just like you can fiddle with the registers. All sorts of such fiddling are possible, and don't break any core assumptions of the utrace API. It's just a question of what fiddling is really a good idea and how to mediate higher-level choices about that. You don't risk any bad effects beyond what some unhelpful engine (or just userland run wild) might do anyway, i.e. scrambling user registers and siginfo_t so they foul up application behavior. But that's just a baseline limit on harm. At higher levels you want to cooperate with other engines so they all work together usefully in practice. The API offers only one mechanism to synchronize with anyone else fiddling such things. That is to do the fiddling in your report_* callbacks where you are explicitly serialized with the callbacks of other engines and have specified ways to be sure you observe what they do. I think it's entirely reasonable to say that only ptrace should fiddle with siginfo_t outside of report_signal callbacks, just as a convention about what's couth. But that's beyond the scope of the utrace API level itself. Thanks, Roland From roland at redhat.com Mon Aug 24 23:58:21 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 24 Aug 2009 16:58:21 -0700 (PDT) Subject: utrace_stop() && UTRACE_DETACH In-Reply-To: Oleg Nesterov's message of Thursday, 20 August 2009 21:42:51 +0200 <20090820194251.GA29913@redhat.com> References: <20090820194251.GA29913@redhat.com> Message-ID: <20090824235821.328A7414DF@magilla.sf.frob.com> > Suppose the tracer calls utrace_control(UTRACE_DETACH) right before the > tracee calls utrace_stop(). What can we do then? The tracer can't know > the tracee is going to stop, the tracee can't know it should not stop. Yes, I think you're right. I've tried to fix it in commit 00932db. Thanks, Roland From srikar at linux.vnet.ibm.com Tue Aug 25 06:16:38 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Tue, 25 Aug 2009 11:46:38 +0530 Subject: [PATCH] Fix missing reference count Message-ID: <20090825061638.GA31237@linux.vnet.ibm.com> Hi Frank, Please review and accept the patch. Missed utrace_engine_put() could lead to engine leaks After reading through https://www.redhat.com/archives/utrace-devel/2009-August/msg00093.html mail and from utrace code, it looks like we are leaking references to engine. Hence this patch. Missed utrace_engine_put() could lead to engine leaks. This patch also partially undoes one of my previous changes to gdbstub. Signed-off-by: Srikar Dronamraju --- kernel/ubp_xol.c | 1 + kernel/uprobes_core.c | 1 + kernel/utrace-gdb.c | 1 + 3 files changed, 3 insertions(+), 0 deletions(-) diff --git a/kernel/ubp_xol.c b/kernel/ubp_xol.c index f0a1a10..017b3cf 100644 --- a/kernel/ubp_xol.c +++ b/kernel/ubp_xol.c @@ -130,6 +130,7 @@ static int xol_create_engine(struct pid *pid, struct ubp_xol_area *area) WARN_ON(result == -EINPROGRESS); kref_get(&area->kref); put_pid(pid); + utrace_engine_put(engine); return 0; } diff --git a/kernel/uprobes_core.c b/kernel/uprobes_core.c index f059e3c..74d568b 100644 --- a/kernel/uprobes_core.c +++ b/kernel/uprobes_core.c @@ -640,6 +640,7 @@ static struct uprobe_task *uprobe_add_task(struct pid *p, * with the engine in place, the appropriate report_* callback * should handle it after we release uproc->rwsem. */ + utrace_engine_put(engine); return utask; } diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index d7b3b58..21bf995 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -1200,6 +1200,7 @@ static int proc_gdb_open(struct inode *inode, struct file *filp) if (!ret) ; + utrace_engine_put(p->engine); filp->private_data = p; INIT_LIST_HEAD(& p->link); From srikar at linux.vnet.ibm.com Tue Aug 25 06:18:05 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Tue, 25 Aug 2009 11:48:05 +0530 Subject: [PATCH] Dont attach iff there is an existing gdbstub engine. Message-ID: <20090825061805.GB31237@linux.vnet.ibm.com> gdbstub doesnt connect if an engine already exists. Such an existing engine may not be related to gdbstub. Currently if we trace a process using gdb, insert breakpoints, disconnect and reattach to that same process, gdb fails. What gdbstub probably needs is an exclusive gdbstub engine. i.e If a gdbstub connection exists for a process, we shouldnt be creating a new gdbstub connection. Signed-off-by: Srikar Dronamraju --- kernel/utrace-gdb.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index 21bf995..29e9c05 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -1180,10 +1180,11 @@ static int proc_gdb_open(struct inode *inode, struct file *filp) p->at_quiesce_do = UTRACE_RESUME; p->engine = utrace_attach_task(task, - UTRACE_ATTACH_CREATE | - UTRACE_ATTACH_EXCLUSIVE, - &gdb_utrace_ops, - p); + UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &gdb_utrace_ops, + p); if (IS_ERR(p->engine) || p->engine==NULL) { ret = -EBUSY; goto out_free; From wouter at ms14.hinet.net Tue Aug 25 10:56:18 2009 From: wouter at ms14.hinet.net (Noll Cleveland) Date: Tue, 25 Aug 2009 02:56:18 -0800 Subject: Your easy way to become one of those healthy guys. Message-ID: <001601ca256a$4a832430$b4cac292@CACEFP811762yjcohj> Always wood, never flaccid http://muyqi.foshaocfu.com/ From oleg at redhat.com Tue Aug 25 13:06:25 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 25 Aug 2009 15:06:25 +0200 Subject: [PATCH 15] fix "Fiddle code to avoid warnings" Message-ID: <20090825130625.GA12845@redhat.com> Roland, you pushed 2 commits into utrace-ptrace, and the second one "ptrace_do_detach: Fiddle code to avoid warnings." c8315d350406b46d6f8bb965f5ebfbf13d7e391d is not right. - If release == T then ptrace_detach_task() is meaningless, but this is minor. - If release == T then we must do release_task(), and detach must be T too. IOW, with this change release_task() is never called ad we leak the dead task. Instead we do ptrace_detach_task() which is not needed. --- kernel/ptrace.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) --- PU/kernel/ptrace.c~15_GIT_FIXUP 2009-08-25 14:14:39.000000000 +0200 +++ PU/kernel/ptrace.c 2009-08-25 14:56:01.000000000 +0200 @@ -738,8 +738,7 @@ static void ptrace_do_detach(struct task * This tracee can be already killed. Make sure de_thread() or * our sub-thread doing do_wait() didn't do release_task() yet. */ - detach = tracee->ptrace != 0; - release = false; + detach = (tracee->ptrace != 0); if (likely(detach)) { if (valid_signal(data)) tracee->exit_code = data; @@ -747,10 +746,12 @@ static void ptrace_do_detach(struct task } write_unlock_irq(&tasklist_lock); - if (likely(detach)) - ptrace_detach_task(tracee, data); - else if (unlikely(release)) - release_task(tracee); + if (likely(detach)) { + if (unlikely(release)) + release_task(tracee); + else + ptrace_detach_task(tracee, data); + } } int ptrace_detach(struct task_struct *child, unsigned int data) From oleg at redhat.com Tue Aug 25 16:52:39 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 25 Aug 2009 18:52:39 +0200 Subject: [PATCH 0/5] utrace-ptrace-mini: rfc hacks Message-ID: <20090825165239.GA19086@redhat.com> (On top of utrace branch, this has nothing to do with the previous changes I sent). Roland, this is the series of hacks, not patches. Not complete and I didn't even try to boot the kernel. Just to explain what I mean. Two questions: 1. do you think this _can_ work as a first version of utrace-ptrace? "work" means: could look as utrace-ptrace for 2.6.32, then we make incremental changes on top. 2. do you think it makes any sense to do something like this? This series adds the "fake" ptrace_utrace_ops. We never use these ops, we only use engine to make stops/wakeups utrace-friendly. Signals. ptrace processes a signal after all other attached engines. Why? 2.6.32 is close. I doubt I can make the full-blown (and _working_) implementation before the merge window. And I am nervous because I doubt. So I finally decided to at least discuss this option. Oleg. From oleg at redhat.com Tue Aug 25 16:52:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 25 Aug 2009 18:52:42 +0200 Subject: [PATCH 1] utrace-ptrace-mini: get_signal_to_deliver: always call ptrace_signal() Message-ID: <20090825165242.GA19094@redhat.com> No functional changes, preparation. Change get_signal_to_deliver() so that ptrace_signal() is called even if utrace returns signr != 0. I think this is more correct now, when ptrace is not implemented on top of utrace. When we change ptrace to use ->report_signal() ptrace_signal() should be killed/ifdefed anyway, so afaic this change will not interfere with utrace-ptrace. --- kernel/signal.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) --- MINI/kernel/signal.c~1_SIGNALS_TWEAK 2009-08-17 11:56:56.000000000 +0200 +++ MINI/kernel/signal.c 2009-08-25 15:51:42.000000000 +0200 @@ -1843,18 +1843,16 @@ relock: else { signr = dequeue_signal(current, ¤t->blocked, info); + ka = &sighand->action[signr-1]; + } - if (!signr) - break; /* will return 0 */ - - if (signr != SIGKILL) { - signr = ptrace_signal(signr, info, - regs, cookie); - if (!signr) - continue; - } + if (!signr) + break; /* will return 0 */ - ka = &sighand->action[signr-1]; + if (signr != SIGKILL) { + signr = ptrace_signal(signr, info, regs, cookie); + if (!signr) + continue; } if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ From oleg at redhat.com Tue Aug 25 16:52:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 25 Aug 2009 18:52:44 +0200 Subject: [PATCH 2] utrace-ptrace-mini: introduce the empty ptrace_utrace_ops Message-ID: <20090825165244.GA19097@redhat.com> Introduce the empty ptrace_utrace_ops, change attach/detach to add/remove utrace_engine whis this ops. For this series it will be empty, no methods and we never call set_events(). We use it only to cooperate with other engines when it comes to stop/wakeup. --- kernel/ptrace.c | 147 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 95 insertions(+), 52 deletions(-) --- MINI/kernel/ptrace.c~2_PTRACE_ENGINE 2009-07-13 17:44:27.000000000 +0200 +++ MINI/kernel/ptrace.c 2009-08-25 17:00:35.000000000 +0200 @@ -24,6 +24,43 @@ #include #include +static const struct utrace_engine_ops ptrace_utrace_ops; /* empty */ + +static void ptrace_detach_task(struct task_struct *child) +{ + struct utrace_engine *engine; + int ret; + + engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (unlikely(IS_ERR(engine))) + return; + + ret = utrace_control(child, engine, UTRACE_DETACH); + WARN_ON(ret && ret != -EINPROGRESS && + ret != -ESRCH && ret != -EALREADY); + + utrace_engine_put(engine); +} + +static int ptrace_attach_task(struct task_struct *tracee) +{ + struct utrace_engine *engine; + + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (unlikely(IS_ERR(engine))) { + int err = PTR_ERR(engine); + if (err != -ESRCH && err != -ERESTARTNOINTR) + err = -EPERM; + return err; + } + + utrace_engine_put(engine); + return 0; +} /* * ptrace a task: make the debugger its new parent and @@ -196,19 +233,20 @@ int ptrace_attach(struct task_struct *ta task_lock(task); retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); - if (!retval && exclude_ptrace(task)) - retval = -EBUSY; task_unlock(task); if (retval) goto unlock_creds; + retval = ptrace_attach_task(task); + if (unlikely(retval)) + goto unlock_creds; + write_lock_irq(&tasklist_lock); retval = -EPERM; if (unlikely(task->exit_state)) goto unlock_tasklist; - if (task->ptrace) - goto unlock_tasklist; + BUG_ON(task->ptrace); task->ptrace = PT_PTRACED; if (capable(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; @@ -233,27 +271,30 @@ out: */ int ptrace_traceme(void) { - int ret = -EPERM; + bool detach = true; + int ret = ptrace_attach_task(current); - if (exclude_ptrace(current)) /* XXX locking */ - return -EBUSY; + if (unlikely(ret)) + return ret; + ret = -EPERM; write_lock_irq(&tasklist_lock); - /* Are we already being traced? */ - if (!current->ptrace) { - ret = security_ptrace_traceme(current->parent); - /* - * Check PF_EXITING to ensure ->real_parent has not passed - * exit_ptrace(). Otherwise we don't report the error but - * pretend ->real_parent untraces us right after return. - */ - if (!ret && !(current->real_parent->flags & PF_EXITING)) { - current->ptrace = PT_PTRACED; - __ptrace_link(current, current->real_parent); - } + BUG_ON(current->ptrace); + ret = security_ptrace_traceme(current->parent); + /* + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. + */ + if (!ret && !(current->real_parent->flags & PF_EXITING)) { + current->ptrace = PT_PTRACED; + __ptrace_link(current, current->real_parent); + detach = false; } write_unlock_irq(&tasklist_lock); + if (detach) + ptrace_detach_task(current); return ret; } @@ -305,56 +346,58 @@ static bool __ptrace_detach(struct task_ return false; } -int ptrace_detach(struct task_struct *child, unsigned int data) +static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) { - bool dead = false; - - if (!valid_signal(data)) - return -EIO; - - /* Architecture-specific hardware disable .. */ - ptrace_disable(child); - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + bool detach, release; write_lock_irq(&tasklist_lock); /* - * This child can be already killed. Make sure de_thread() or + * This tracee can be already killed. Make sure de_thread() or * our sub-thread doing do_wait() didn't do release_task() yet. */ - if (child->ptrace) { - child->exit_code = data; - dead = __ptrace_detach(current, child); - if (!child->exit_state) - wake_up_process(child); + detach = (tracee->ptrace != 0); + if (likely(detach)) { + if (valid_signal(data)) + tracee->exit_code = data; + release = __ptrace_detach(current, tracee); } write_unlock_irq(&tasklist_lock); - if (unlikely(dead)) - release_task(child); + if (likely(detach)) { + if (unlikely(release)) + release_task(tracee); + else + ptrace_detach_task(tracee); + } +} + +int ptrace_detach(struct task_struct *child, unsigned int data) +{ + if (!valid_signal(data)) + return -EIO; + + ptrace_do_detach(child, data); return 0; } -/* - * Detach all tasks we were using ptrace on. - */ void exit_ptrace(struct task_struct *tracer) { - struct task_struct *p, *n; - LIST_HEAD(ptrace_dead); - - write_lock_irq(&tasklist_lock); - list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) { - if (__ptrace_detach(tracer, p)) - list_add(&p->ptrace_entry, &ptrace_dead); - } - write_unlock_irq(&tasklist_lock); + for (;;) { + struct task_struct *tracee = NULL; - BUG_ON(!list_empty(&tracer->ptraced)); + read_lock(&tasklist_lock); + if (!list_empty(&tracer->ptraced)) { + tracee = list_first_entry(&tracer->ptraced, + struct task_struct, ptrace_entry); + get_task_struct(tracee); + } + read_unlock(&tasklist_lock); + if (!tracee) + break; - list_for_each_entry_safe(p, n, &ptrace_dead, ptrace_entry) { - list_del_init(&p->ptrace_entry); - release_task(p); + ptrace_do_detach(tracee, -1); + put_task_struct(tracee); } } From oleg at redhat.com Tue Aug 25 16:52:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 25 Aug 2009 18:52:46 +0200 Subject: [PATCH 3] utrace-ptrace-mini: ptrace_stop: make it utrace-friendly Message-ID: <20090825165246.GA19100@redhat.com> Introduce xxx_utrace_stop() which notifies engine we are going to stop. It calls report_quiesce(0), but report.action = UTRACE_STOP instead of UTRACE_RESUME. Change ptrace_stop() to use xxx_utrace_stop(). Yes, it is racy and can stop after detach, but afaics this is fixeable when utrace_stop() will be fixed. Change utrace_stop() to use another ugly hack, xxx_ptrace_notify_stop(), to notify the parent. --- include/linux/sched.h | 1 + include/linux/utrace.h | 3 +++ include/linux/ptrace.h | 4 ++++ kernel/utrace.c | 20 ++++++++++++++++++++ kernel/ptrace.c | 36 ++++++++++++++++++++++++++++++++++++ kernel/signal.c | 24 +++--------------------- 6 files changed, 67 insertions(+), 21 deletions(-) --- MINI/include/linux/sched.h~3_PTRACE_NOTIFY 2009-08-25 17:00:35.000000000 +0200 +++ MINI/include/linux/sched.h 2009-08-25 17:11:38.000000000 +0200 @@ -1980,6 +1980,7 @@ extern int kill_pgrp(struct pid *pid, in extern int kill_pid(struct pid *pid, int sig, int priv); extern int kill_proc_info(int, struct siginfo *, pid_t); extern int do_notify_parent(struct task_struct *, int); +extern void do_notify_parent_cldstop(struct task_struct *, int); extern void force_sig(int, struct task_struct *); extern void force_sig_specific(int, struct task_struct *); extern int send_sig(int, struct task_struct *, int); --- MINI/include/linux/utrace.h~3_PTRACE_NOTIFY 2009-08-17 11:56:56.000000000 +0200 +++ MINI/include/linux/utrace.h 2009-08-25 17:20:24.000000000 +0200 @@ -624,6 +624,9 @@ int __must_check utrace_finish_examine(s struct utrace_engine *, struct utrace_examiner *); +void xxx_utrace_stop(void); + + /** * utrace_control_pid - control a thread being traced by a tracing engine * @pid: thread to affect --- MINI/include/linux/ptrace.h~3_PTRACE_NOTIFY 2009-08-25 17:00:35.000000000 +0200 +++ MINI/include/linux/ptrace.h 2009-08-25 17:35:45.000000000 +0200 @@ -94,6 +94,10 @@ extern void __ptrace_link(struct task_st struct task_struct *new_parent); extern void __ptrace_unlink(struct task_struct *child); extern void exit_ptrace(struct task_struct *tracer); + +extern void ptrace_do_stop(void); +void xxx_ptrace_notify_stop(struct task_struct *); + #define PTRACE_MODE_READ 1 #define PTRACE_MODE_ATTACH 2 /* Returns 0 on success, -errno on denial. */ --- MINI/kernel/utrace.c~3_PTRACE_NOTIFY 2009-08-25 12:33:17.000000000 +0200 +++ MINI/kernel/utrace.c 2009-08-25 17:33:51.000000000 +0200 @@ -398,6 +398,9 @@ static void utrace_stop(struct task_stru spin_unlock_irq(&task->sighand->siglock); spin_unlock(&utrace->lock); + if (task_ptrace(task)) + xxx_ptrace_notify_stop(task); + schedule(); /* @@ -1819,6 +1822,23 @@ void utrace_resume(struct task_struct *t finish_resume_report(&report, task, utrace); } +void xxx_utrace_stop(void) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + struct utrace_engine *engine; + INIT_REPORT(report); + + report.action = UTRACE_STOP; + + start_report(utrace); + + list_for_each_entry(engine, &utrace->attached, entry) + start_callback(utrace, &report, engine, task, 0); + + finish_resume_report(&report, task, utrace); +} + /* * Return true if current has forced signal_pending(). * --- MINI/kernel/ptrace.c~3_PTRACE_NOTIFY 2009-08-25 17:00:35.000000000 +0200 +++ MINI/kernel/ptrace.c 2009-08-25 17:41:47.000000000 +0200 @@ -62,6 +62,42 @@ static int ptrace_attach_task(struct tas return 0; } +void ptrace_do_stop(void) +{ + struct utrace_engine *engine; + + engine = utrace_attach_task(current, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (unlikely(IS_ERR(engine))) + return; + + utrace_control(current, engine, UTRACE_STOP); /* unneeded curently */ + + engine->data = (void*)1; /* marker for xxx_ptrace_notify_stop() */ + xxx_utrace_stop(); + engine->data = NULL; + + utrace_engine_put(engine); +} + +void xxx_ptrace_notify_stop(struct task_struct *task) +{ + struct utrace_engine *engine; + + engine = utrace_attach_task(task, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (unlikely(IS_ERR(engine))) + return; + + if (engine->data) { + read_lock(&tasklist_lock); + do_notify_parent_cldstop(task, CLD_TRAPPED); + read_unlock(&tasklist_lock); + } + + utrace_engine_put(engine); +} + /* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. --- MINI/kernel/signal.c~3_PTRACE_NOTIFY 2009-08-25 17:00:35.000000000 +0200 +++ MINI/kernel/signal.c 2009-08-25 17:11:38.000000000 +0200 @@ -1479,7 +1479,7 @@ int do_notify_parent(struct task_struct return ret; } -static void do_notify_parent_cldstop(struct task_struct *tsk, int why) +void do_notify_parent_cldstop(struct task_struct *tsk, int why) { struct siginfo info; unsigned long flags; @@ -1595,32 +1595,14 @@ static void ptrace_stop(int exit_code, i return; } - /* - * If there is a group stop in progress, - * we must participate in the bookkeeping. - */ - if (current->signal->group_stop_count > 0) - --current->signal->group_stop_count; - current->last_siginfo = info; current->exit_code = exit_code; - - /* Let the debugger run. */ - __set_current_state(TASK_TRACED); spin_unlock_irq(¤t->sighand->siglock); read_lock(&tasklist_lock); if (may_ptrace_stop()) { - do_notify_parent_cldstop(current, CLD_TRAPPED); - /* - * Don't want to allow preemption here, because - * sys_ptrace() needs this task to be inactive. - * - * XXX: implement read_unlock_no_resched(). - */ - preempt_disable(); read_unlock(&tasklist_lock); - preempt_enable_no_resched(); - schedule(); + + ptrace_do_stop(); } else { /* * By the time we got the lock, our tracer went away. From oleg at redhat.com Tue Aug 25 16:52:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 25 Aug 2009 18:52:49 +0200 Subject: [PATCH 4] utrace-ptrace-mini: change ptrace_check_attach() Message-ID: <20090825165249.GA19108@redhat.com> Copy-and-paste. Roland, ptrace_check_attach()->utrace_control(UTRACE_STOP) is not right. We should not do mark_engine_wants_stop() and set ->report from ptrace_check_attach(). It should be "passive", except s/STOPPED/TRACED/. for this series this is not right too... --- kernel/ptrace.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) --- MINI/kernel/ptrace.c~4_CK_ATTACH 2009-08-25 17:41:47.000000000 +0200 +++ MINI/kernel/ptrace.c 2009-08-25 17:54:50.000000000 +0200 @@ -159,35 +159,29 @@ void __ptrace_unlink(struct task_struct */ int ptrace_check_attach(struct task_struct *child, int kill) { - int ret = -ESRCH; + struct utrace_engine *engine; + struct utrace_examiner exam; + int ret; + + if (child->parent != current) + return -ESRCH; + + engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (IS_ERR(engine)) + return -ESRCH; /* - * We take the read lock around doing both checks to close a - * possible race where someone else was tracing our child and - * detached between these two checks. After this locked check, - * we are sure that this is our traced child and that can only - * be changed by us so it's not changing right after this. + * Make sure our engine has already stopped the child. + * Then wait for it to be off the CPU. */ - read_lock(&tasklist_lock); - if ((child->ptrace & PT_PTRACED) && child->parent == current) { - ret = 0; - /* - * child->sighand can't be NULL, release_task() - * does ptrace_unlink() before __exit_signal(). - */ - spin_lock_irq(&child->sighand->siglock); - if (task_is_stopped(child)) - child->state = TASK_TRACED; - else if (!task_is_traced(child) && !kill) - ret = -ESRCH; - spin_unlock_irq(&child->sighand->siglock); - } - read_unlock(&tasklist_lock); + ret = 0; + if (utrace_control(child, engine, UTRACE_STOP) || + utrace_prepare_examine(child, engine, &exam)) + ret = -ESRCH; - if (!ret && !kill) - ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH; + utrace_engine_put(engine); - /* All systems go.. */ return ret; } From oleg at redhat.com Tue Aug 25 16:52:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 25 Aug 2009 18:52:52 +0200 Subject: [PATCH 5] utrace-ptrace-mini: make wakeups utrace-friendly Message-ID: <20090825165252.GA19111@redhat.com> Introduce the "utrace-friendly" ptrace_wake_up() and use it instead of wake_up_process(). Kill ptrace_untrace(), detach should wake up the tracee correctly via UTRACE_DETACH. --- kernel/ptrace.c | 47 ++++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) --- MINI/kernel/ptrace.c~5_WAKEUP 2009-08-25 17:54:50.000000000 +0200 +++ MINI/kernel/ptrace.c 2009-08-25 18:09:38.000000000 +0200 @@ -98,6 +98,25 @@ void xxx_ptrace_notify_stop(struct task_ utrace_engine_put(engine); } +static void ptrace_wake_up(struct task_struct *task) +{ + struct utrace_engine *engine; + + engine = utrace_attach_task(task, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (unlikely(IS_ERR(engine))) + return; + + if (task_is_stopped_or_traced(task)) { + spin_lock_irq(&task->sighand->siglock); + task->signal->flags &= ~SIGNAL_STOP_STOPPED; + spin_unlock_irq(&task->sighand->siglock); + } + + utrace_control(task, engine, UTRACE_RESUME); + utrace_engine_put(engine); +} + /* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. @@ -112,30 +131,6 @@ void __ptrace_link(struct task_struct *c } /* - * Turn a tracing stop into a normal stop now, since with no tracer there - * would be no way to wake it up with SIGCONT or SIGKILL. If there was a - * signal sent that would resume the child, but didn't because it was in - * TASK_TRACED, resume it now. - * Requires that irqs be disabled. - */ -static void ptrace_untrace(struct task_struct *child) -{ - spin_lock(&child->sighand->siglock); - if (task_is_traced(child)) { - /* - * If the group stop is completed or in progress, - * this thread was already counted as stopped. - */ - if (child->signal->flags & SIGNAL_STOP_STOPPED || - child->signal->group_stop_count) - __set_task_state(child, TASK_STOPPED); - else - signal_wake_up(child, 1); - } - spin_unlock(&child->sighand->siglock); -} - -/* * unptrace a task: move it back to its original parent and * remove it from the ptrace list. * @@ -150,8 +145,6 @@ void __ptrace_unlink(struct task_struct list_del_init(&child->ptrace_entry); arch_ptrace_untrace(child); - if (task_is_traced(child)) - ptrace_untrace(child); } /* @@ -590,7 +583,7 @@ static int ptrace_resume(struct task_str } child->exit_code = data; - wake_up_process(child); + ptrace_wake_up(child); return 0; } From oleg at redhat.com Tue Aug 25 17:03:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 25 Aug 2009 19:03:22 +0200 Subject: [PATCH 2] utrace-ptrace-mini: introduce the empty ptrace_utrace_ops In-Reply-To: <20090825165244.GA19097@redhat.com> References: <20090825165244.GA19097@redhat.com> Message-ID: <20090825170322.GA20308@redhat.com> On 08/25, Oleg Nesterov wrote: > > Introduce the empty ptrace_utrace_ops, change attach/detach to add/remove > utrace_engine whis this ops. Forgot to mention, I ignored auto-attach/CLONE_PTRACE for now. Oleg. From roland at redhat.com Tue Aug 25 20:16:56 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 25 Aug 2009 13:16:56 -0700 (PDT) Subject: [PATCH 15] fix "Fiddle code to avoid warnings" In-Reply-To: Oleg Nesterov's message of Tuesday, 25 August 2009 15:06:25 +0200 <20090825130625.GA12845@redhat.com> References: <20090825130625.GA12845@redhat.com> Message-ID: <20090825201656.F1C08411E3@magilla.sf.frob.com> Oops, sorry about that. I've tweaked it so it should be right now, and also still avoids the compiler warnings. Thanks, Roland From Shop9 at Mail.ServicetoYou.info Tue Aug 25 20:58:01 2009 From: Shop9 at Mail.ServicetoYou.info (Jessie) Date: Tue, 25 Aug 2009 20:58:01 -0000 Subject: SAVE 28-68% on name brand Sneakers Message-ID: Dear utrace-devel at redhat.com: Discount Sneakers: Save 59% on name brand sport shoes to you. We assure you reliable quality, best price and fast shipping. We also sell name brand Handbags, Fashion Shoes, Sport Clothes and other famous brands including Nike, Converse, Adidas, Puma, Kappa, Prada, Gucci, Louis Vuitton and UGG Australia etc. Let us know if you have any needs. Services Support Brand at Infoappender.com Other discount name brand products: T-shirts, Jeans, Hats, Wallets, Belts, Sunglasses, Wig, Wrist-watches, and other series of products. From fa.van.heeren at bvg.fin.ec Wed Aug 26 00:59:57 2009 From: fa.van.heeren at bvg.fin.ec (Nina Roe) Date: Wed, 26 Aug 2009 00:59:57 -0000 Subject: Never loose hope to get your healthy living back. Message-ID: <20090826005957.1000604@bvg.fin.ec> REad about ancient intimacy enhancer! http://xlhrih.wingdeal.com/ From oleg at redhat.com Wed Aug 26 10:27:59 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 26 Aug 2009 12:27:59 +0200 Subject: [PATCH] utrace_stop: fix UTRACE_DETACH race In-Reply-To: <20090824235821.328A7414DF@magilla.sf.frob.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> Message-ID: <20090826102759.GA5455@redhat.com> "utrace_stop: fix UTRACE_DETACH race" commit 00932dbe24bd4273e6d723baa9342e7b3e248911, > @@ -808,7 +808,25 @@ static void utrace_stop(struct task_struct *task, struct utrace *utrace, > * waking us up, we must synchronize with the signal bookkeeping > * for stop signals and SIGCONT. > */ > +relock: > spin_lock(&utrace->lock); > + > + if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { > + /* > + * UTRACE_DETACH was used in some utrace_control() > + * call since the last time we ran utrace_reset(). I believe the comment and "unlikely" above are not right. Neither utrace_control(STOP) nor finish_callback(action => STOP) set ENGINE_STOP in ->utrace_flags. They change engine->flags only, and ENGINE_STOP can only "migrate" to ->utrace_flags after utrace_reset(). Yes, the only reason (but see below) we check ENGINE_STOP here is that perhaps UTRACE_DETACH was used, but if we don't see ENGINE_STOP this doesn't mean UTRACE_DETACH was used. This case is not unlikely, for example ENGINE_STOP is cleared after the previous wakeup. We are running, if ENGINE_STOP is set, UTRACE_STOP was used and utrace_reset() was called after that. Otherwise, _perhaps_ it was cleared by UTRACE_DETACH. > + enum utrace_resume_action stop = UTRACE_STOP; > + utrace_reset(task, utrace, &stop); > + if (stop != UTRACE_STOP) > + return; This doesn't look right. Note that utrace_reset() changes *action only when flags == 0, this is only possible if there are no attached engines. If we have another engine but engine_wants_stop() == F, stop is not changed and we are going to spin forever. > @@ -1083,6 +1101,16 @@ int utrace_control(struct task_struct *target, > resume = resume || utrace_do_stop(target, utrace); > if (!resume) { > /* > + * This is a marker in case utrace_stop() gets > + * utrace->lock before utrace_reset() does, > + * meaning UTRACE_STOP was just returned from a > + * callback before our UTRACE_DETACH is seen. > + * It must double-check that our now-detached > + * engine was not the only reason to stop. > + */ > + target->utrace_flags &= ~ENGINE_STOP; Well, yes. But this only helps for ENGINE_STOP. Consider utrace_control(UTRACE_STOP); utrace_control(UTRACE_RESUME); the tracee can stop. OK, this is not as critical as UTRACE_DETACH problem, but still. Perhaps RESUME and INTERRUPT interrupt should clear ENGINE_STOP too? Oleg. From oleg at redhat.com Wed Aug 26 10:41:50 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 26 Aug 2009 12:41:50 +0200 Subject: [PATCH] utrace: fix utrace_stop()->utrace_reset() path In-Reply-To: <20090826102759.GA5455@redhat.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> <20090826102759.GA5455@redhat.com> Message-ID: <20090826104150.GA6503@redhat.com> utrace_reset(action) changes *action only when there are no attached engines, utrace_stop() can't rely on "stop != UTRACE_STOP" check. Change utrace_stop() to call utrace_reset(action => NULL) and recheck ->utrace_flags. action => NULL may cause the unnecessary utrace_wakeup(current), but this case is unlikely and harmless. Also, move "unlikely()" from the first check to the second, afaics this matches the reality. Well, as I said I believe the comment is misleading, but I can't suggest something better. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~1_STOP_DETACH_FIX 2009-08-26 11:42:17.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-26 12:30:38.000000000 +0200 @@ -811,7 +811,7 @@ static void utrace_stop(struct task_stru relock: spin_lock(&utrace->lock); - if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { + if (!(task->utrace_flags & ENGINE_STOP)) { /* * UTRACE_DETACH was used in some utrace_control() * call since the last time we ran utrace_reset(). @@ -820,9 +820,8 @@ relock: * would be nobody to resume us. So we must check over * still-attached engines and recompute the flags. */ - enum utrace_resume_action stop = UTRACE_STOP; - utrace_reset(task, utrace, &stop); - if (stop != UTRACE_STOP) + utrace_reset(task, utrace, NULL); + if (unlikely(!(task->utrace_flags & ENGINE_STOP))) return; goto relock; } From oleg at redhat.com Wed Aug 26 12:03:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 26 Aug 2009 14:03:53 +0200 Subject: [PATCH] utrace: fix utrace->signal_handler "leakage" Message-ID: <20090826120353.GA10505@redhat.com> A tracee must not return to user mode with ->signal_handler = 1. And, ->signal_handler = 1 must not survive when all detaches are detached. But, suppose (for simplicity) we have a single engine attached, and utrace_signal_handler() sets ->signal_handler = 1. Suppose signal_pending() = T. The tracee calls get_signal_to_deliver() again. It is possible that the tracee will call tracehook_notify_jctl() before tracehook_get_signal(). Because another thread can start the group stop, or because SIGNAL_STOP_CONTINUED is set. The tracer does UTRACE_DETACH or ->report_jctl() returns UTRACE_DETACH. REPORT()->finish_report() notices report->detaches and calls utrace_reset(). utrace_reset() completes UTRACE_DETACH, and clears ->utrace_flags. The tracee return to user mode bypassing utrace_get_signal() and utrace_resume() because task_utrace_flags() == 0. So far this is OK, the task is not traced. But, when the new tracer attaches, utrace->signal_handler is still true, the next report_signal will use UTRACE_SIGNAL_HANDLER. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~2_SIGNAL_HANDLER_LEAK 2009-08-26 12:30:38.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-26 13:51:10.000000000 +0200 @@ -768,23 +768,20 @@ static void utrace_reset(struct task_str } task->utrace_flags = flags; - - if (wake) - utrace_wakeup(task, utrace); - - /* - * If any engines are left, we're done. - */ - spin_unlock(&utrace->lock); if (!flags) { /* * No more engines, cleared out the utrace. */ + utrace->interrupt = utrace->report = utrace->signal_handler = 0; if (action) *action = UTRACE_RESUME; } + if (wake) + utrace_wakeup(task, utrace); + spin_unlock(&utrace->lock); + put_detached_list(&detached); } From srikar at linux.vnet.ibm.com Wed Aug 26 12:16:56 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 26 Aug 2009 17:46:56 +0530 Subject: [PATCH 0/2] Allow deferred registration if thread is stopped. Message-ID: <20090826121656.17745.57506.sendpatchset@srdronam.in.ibm.com> Hi, This is an attempt to solve the first problem that I talked in the previous patchset. 1. register_uprobe/unregister_uprobe may cause deadlock Currently if uprobes engine were in the midst of singlestepping a breakpoint, it wouldnt allow register/unregister of probes to continue until the singlestep operation completes. However tracing thread that could be registering/unregistering a probe could have already requested the thread that was in the midst of singlestepping to STOP. This leads to a deadlock, - register/unregistering thread waits for reg/unreg to complete before resuming the thread - singlestepping thread waiting for it to be resumed and complete singlestepping before it could quiesce and allow register/unregister to complete. This patch tries to fix this problem by using the existing defer_registration. Once we defer the request, the registering thread would then resume the singlestepping thread which would pick up the deferred registration. Subject: [PATCH 0/2] Fixes to gdbstub. File: /tmp/gdbstub-patches/2/intro Subject: [PATCH 1/2] Defer register/unregister if thread is stopped. File: /tmp/gdbstub-patches/2/uc_make_defer_un_register_uprobe.patch Subject: [PATCH 2/2] Allow deferred register/unregister of uprobes. File: /tmp/gdbstub-patches/2/gs_use_deferred_register_uprobe.patch -- Thanks and Regards Srikar Dronamraju From srikar at linux.vnet.ibm.com Wed Aug 26 12:17:06 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 26 Aug 2009 17:47:06 +0530 Subject: [PATCH 1/2] Defer register/unregister if thread is stopped. In-Reply-To: <20090826121656.17745.57506.sendpatchset@srdronam.in.ibm.com> References: <20090826121656.17745.57506.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090826121706.17745.96746.sendpatchset@srdronam.in.ibm.com> Make register_uprobe/ unregister_uprobe to defer if the task having an active probe is stopped or traced Signed-off-by: Srikar Dronamraju Reviewed-by: Jim Keniston --- kernel/uprobes_core.c | 78 +++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 72 insertions(+), 6 deletions(-) diff --git a/kernel/uprobes_core.c b/kernel/uprobes_core.c index 74d568b..7cea30b 100644 --- a/kernel/uprobes_core.c +++ b/kernel/uprobes_core.c @@ -824,12 +824,35 @@ static void purge_uprobe(struct uprobe_kimg *uk) uprobe_free_probept(ppt); } -/* Runs with utask->uproc read-locked. Returns -EINPROGRESS on success. */ +/* + * Runs with utask->uproc locked. + * read lock if called from uprobe handler. + * else write lock. + * Returns -EINPROGRESS on success. + * Returns -EBUSY if a request for defer registration already exists. + * Returns 0 if we have deferred request for both register/unregister. + * + */ static int defer_registration(struct uprobe *u, int regflag, struct uprobe_task *utask) { - struct deferred_registration *dr; + struct deferred_registration *dr, *d; + /* Check if we already have such a defer request */ + list_for_each_entry_safe(dr, d, &utask->deferred_registrations, list) { + if (dr->uprobe == u) { + if (dr->regflag != regflag) { + /* same as successful register + unregister */ + list_del(&dr->list); + kfree(dr); + return 0; + } else + /* we already have identical request */ + return -EBUSY; + } + } + + /* We have a new unique request */ dr = kmalloc(sizeof(struct deferred_registration), GFP_USER); if (!dr) return -ENOMEM; @@ -885,7 +908,8 @@ int register_uprobe(struct uprobe *u) return -ESRCH; cur_utask = uprobe_find_utask(current); - if (cur_utask && cur_utask->active_probe) { + if (cur_utask && (cur_utask->state == UPTASK_TRAMPOLINE_HIT || + cur_utask->state == UPTASK_BP_HIT)) { /* * Called from handler; cur_utask->uproc is read-locked. * Do this registration later. @@ -898,9 +922,36 @@ int register_uprobe(struct uprobe *u) mutex_lock(&uproc_mutex); uproc = uprobe_find_process(p); - if (uproc) + if (uproc) { + struct uprobe_task *utask; + mutex_unlock(&uproc_mutex); - else { + list_for_each_entry(utask, &uproc->thread_list, list) { + if (!utask->active_probe) + continue; + /* + * utask is at a probepoint, but has dropped + * uproc->rwsem to single-step. If utask is + * stopped, then it's probably because some + * other engine has asserted UTRACE_STOP; + * that engine may not allow UTRACE_RESUME + * until register_uprobe() returns. But, for + * reasons we won't go into here, utask wants + * to finish with utask->active_probe before + * allowing handle_pending_uprobes() to run + * (via utask_fake_quiesce()). So we defer this + * registration operation; it will be run after + * utask->active_probe is taken care of. + */ + BUG_ON(utask->state != UPTASK_SSTEP); + if (task_is_stopped_or_traced(utask->tsk)) { + put_pid(p); + ret = defer_registration(u, 1, utask); + up_write(&uproc->rwsem); + return ret; + } + } + } else { uproc = uprobe_mk_process(p); if (IS_ERR(uproc)) { ret = (int) PTR_ERR(uproc); @@ -1041,6 +1092,7 @@ void unregister_uprobe(struct uprobe *u) struct uprobe_kimg *uk; struct uprobe_probept *ppt; struct uprobe_task *cur_utask, *cur_utask_quiescing = NULL; + struct uprobe_task *utask; if (!u) return; @@ -1049,7 +1101,8 @@ void unregister_uprobe(struct uprobe *u) return; cur_utask = uprobe_find_utask(current); - if (cur_utask && cur_utask->active_probe) { + if (cur_utask && (cur_utask->state == UPTASK_TRAMPOLINE_HIT || + cur_utask->state == UPTASK_BP_HIT)) { /* Called from handler; uproc is read-locked; do this later */ put_pid(p); (void) defer_registration(u, 0, cur_utask); @@ -1067,6 +1120,19 @@ void unregister_uprobe(struct uprobe *u) if (!uproc) return; + list_for_each_entry(utask, &uproc->thread_list, list) { + if (!utask->active_probe) + continue; + + /* See comment in register_uprobe(). */ + BUG_ON(utask->state != UPTASK_SSTEP); + if (task_is_stopped_or_traced(utask->tsk)) { + put_pid(p); + (void) defer_registration(u, 0, utask); + up_write(&uproc->rwsem); + return; + } + } uk = (struct uprobe_kimg *)u->kdata; if (!uk) /* From srikar at linux.vnet.ibm.com Wed Aug 26 12:17:16 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 26 Aug 2009 17:47:16 +0530 Subject: [PATCH 2/2] Allow deferred register/unregister of uprobes. In-Reply-To: <20090826121656.17745.57506.sendpatchset@srdronam.in.ibm.com> References: <20090826121656.17745.57506.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090826121716.17745.30471.sendpatchset@srdronam.in.ibm.com> commit 20744cb97a3e4aec63ba7b92ce4115170fd468d6 Author: Srikar Dronamraju Date: Wed Aug 19 12:26:15 2009 +0530 Use deferred registration facility for register_uprobe Signed-off-by: Srikar Dronamraju --- kernel/utrace-gdb.c | 75 +++++++++++++++++++++++++++++++++++++------------- 1 files changed, 55 insertions(+), 20 deletions(-) diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index 29e9c05..ac653fe 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -259,6 +259,37 @@ static bool can_gdb_handle_sigtrap(struct pt_regs *regs, void gdb_uprobe_handler(struct uprobe *up, struct pt_regs *regs) { } + +void gdb_register_complete(struct uprobe *up, int regflag, int ret) +{ + if (regflag) { /* register_uprobe */ + struct gdb_uprobe *gup; + struct gdb_connection *gp = NULL, *p = NULL; + + mutex_lock(&gdb_connections_mutex); + list_for_each_entry(p, &gdb_connections, link) { + if (p->target == task_tgid_nr(current)) { + gp = p; + break; + } + } + mutex_unlock(&gdb_connections_mutex); + + if (!gp) + return; + + gup = container_of(up, struct gdb_uprobe, up); + if (ret) { + /* register_uprobe failed */ + kfree(gup); + return; + } + /* Dont bother to use a callback for unregister */ + up->registration_callback = NULL; + INIT_LIST_HEAD(&gup->link); + list_add_tail(&gup->link, &gp->uprobes); + } +} #endif /* CONFIG_HAVE_UPROBES */ @@ -1058,26 +1089,30 @@ static void handle_gdb_command_packet (struct gdb_connection *p, struct task_str } } - if (gup == NULL) { - gup = kzalloc(sizeof (struct gdb_uprobe), GFP_KERNEL); - if (!gup) { - push_output_packet(p, "E04"); - } else { - gup->up.pid = task->tgid; - gup->up.vaddr = arg2; - gup->up.handler = gdb_uprobe_handler; - rc = register_uprobe (& gup->up); - if (rc != 0) { - kfree (gup); - push_output_packet (p, "E06"); - } else { - INIT_LIST_HEAD(& gup->link); - list_add_tail(&gup->link, & p->uprobes); - push_output_packet(p, "OK"); - } - } - } - } + if (gup) /* breakpoint already exists */ + break; + + gup = kzalloc(sizeof(struct gdb_uprobe), GFP_KERNEL); + if (!gup) { + push_output_packet(p, "E04"); + break; + } + gup->up.pid = task->tgid; + gup->up.vaddr = arg2; + gup->up.handler = gdb_uprobe_handler; + gup->up.registration_callback = gdb_register_complete; + rc = register_uprobe(&gup->up); + if (rc && rc != -EINPROGRESS) { + kfree(gup); + push_output_packet(p, "E06"); + } else { + push_output_packet(p, "OK"); + if (!rc) { /* register_uprobe succeed */ + INIT_LIST_HEAD(&gup->link); + list_add_tail(&gup->link, &p->uprobes); + } + } + } break; case 'z': /* TYPE,ADDR,LENGTH */ rc = sscanf(& p->input_buf[2], "%lu,%lx,%lx", &arg1, &arg2, &arg3); From oleg at redhat.com Wed Aug 26 12:17:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 26 Aug 2009 14:17:17 +0200 Subject: [PATCH] utrace: fix utrace_stop()->utrace_reset() path In-Reply-To: <20090826104150.GA6503@redhat.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> <20090826102759.GA5455@redhat.com> <20090826104150.GA6503@redhat.com> Message-ID: <20090826121717.GA11291@redhat.com> On 08/26, Oleg Nesterov wrote: > > action => NULL may cause the unnecessary utrace_wakeup(current), but > this case is unlikely and harmless. Harmless, except BUG_ON(wake != (task != current)). Updated patch below. I was going to remove this BUG_ON() anyway (see other patches I am going to send), but didn't realize it should be killed now. Oleg. ------------------------------------------------------------------------------- [PATCH v2] utrace: fix utrace_stop()->utrace_reset() path utrace_reset(action) change *action only when there are no attached engines, utrace_stop() can't rely on "stop != UTRACE_STOP" check. Change utrace_stop() to call utrace_reset(action => NULL) and recheck ->utrace_flags. action => NULL may cause the unnecessary utrace_wakeup(current), but this case is unlikely and harmless. Also, move "unlikely()" from the first check to the second, afaics this matches the reality. Well, as I said I believe the comment is misleading, but I can't suggest something better. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~1_STOP_DETACH_FIX 2009-08-26 11:42:17.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-26 14:12:29.000000000 +0200 @@ -731,7 +731,6 @@ static void utrace_reset(struct task_str unsigned long flags = 0; LIST_HEAD(detached); bool wake = !action; - BUG_ON(wake != (task != current)); splice_attaching(utrace); @@ -811,7 +810,7 @@ static void utrace_stop(struct task_stru relock: spin_lock(&utrace->lock); - if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { + if (!(task->utrace_flags & ENGINE_STOP)) { /* * UTRACE_DETACH was used in some utrace_control() * call since the last time we ran utrace_reset(). @@ -820,9 +819,8 @@ relock: * would be nobody to resume us. So we must check over * still-attached engines and recompute the flags. */ - enum utrace_resume_action stop = UTRACE_STOP; - utrace_reset(task, utrace, &stop); - if (stop != UTRACE_STOP) + utrace_reset(task, utrace, NULL); + if (unlikely(!(task->utrace_flags & ENGINE_STOP))) return; goto relock; } From oleg at redhat.com Wed Aug 26 13:02:04 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 26 Aug 2009 15:02:04 +0200 Subject: [PATCH 1/2] utrace: utrace_reset: use ->stopped instead of !action Message-ID: <20090826130204.GA14049@redhat.com> (on top of "[PATCH v2] utrace: fix utrace_stop()->utrace_reset() path") The callers of utrace_reset() should be careful with action argument, it affects the wakeup logic. Imho this is a bit fragile and uncler. Change utrace_reset to use ->stopped instead. This way "if (wake)" is always right, regardless of action != NULL, and very understandable. It can't provoke a false wakeup, and it can't miss the wakeup if it is needed. If ->stopped == F, obviously wakeup is not needed, even if the tracee is TASK_STOPPED. IF ->stopped == T, we must not leave the tracee without ENGINE_STOP in TASK_TRACED once we drop utrace->lock. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~3_RESUME_WAKE 2009-08-26 14:19:01.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-26 14:22:58.000000000 +0200 @@ -730,7 +730,7 @@ static void utrace_reset(struct task_str struct utrace_engine *engine, *next; unsigned long flags = 0; LIST_HEAD(detached); - bool wake = !action; + bool wake = utrace->stopped; splice_attaching(utrace); From oleg at redhat.com Wed Aug 26 13:02:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 26 Aug 2009 15:02:09 +0200 Subject: [PATCH 2/2] utrace: utrace_report_death: use utrace_reset(action => NULL) Message-ID: <20090826130209.GA14057@redhat.com> utrace_report_death() can use utrace_reset(action => NULL), the previous patch removed the magical meaning of action. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~4_RESET_CALLERS 2009-08-26 14:22:58.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-26 14:55:51.000000000 +0200 @@ -1729,7 +1729,7 @@ void utrace_report_death(struct task_str */ utrace_reap(task, utrace); else - utrace_reset(task, utrace, &report.action); + utrace_reset(task, utrace, NULL); } /* From thyrglobulin at mail-bericht.nl Wed Aug 26 13:08:32 2009 From: thyrglobulin at mail-bericht.nl (Shifflett) Date: Wed, 26 Aug 2009 21:08:32 +0800 Subject: ." "Oh, no, he comes right Message-ID: <4A952A0D.9080809@mail-bericht.nl> Nd kind magician when we were children," was Hadria's thought, "and now one is grown up, there is no disillusion. He is a good and kind magician still." He seemed indeed to have the power to conjure forth from their hiding-places, the finer qualities of mind and temperament, which had lain dormant, perhaps for years, buried beneath daily accumulations of little car -------------- next part -------------- A non-text attachment was scrubbed... Name: synephrine.jpg Type: image/jpeg Size: 9047 bytes Desc: not available URL: From oleg at redhat.com Wed Aug 26 17:31:48 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 26 Aug 2009 19:31:48 +0200 Subject: [PATCH 1/3] utrace_do_stop: don't set ->stopped when ->exit_state Message-ID: <20090826173148.GA28823@redhat.com> The logic is correct. Just I think it would be tidier to avoid setting utrace->stopped when the task is dead. It doesn't hurt, but it is not needed (and _looks_ confusing imho). We can just return true, this is enough for the caller. In fact, it seems to me "if (exit_state)" case is not needed at all, see "[PATCH 3/3]". Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~5_EXIT_STATE_STOPPED 2009-08-26 14:55:51.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-26 16:53:49.000000000 +0200 @@ -668,7 +668,7 @@ static bool utrace_do_stop(struct task_s * utrace_report_death(), or never will. */ if (!(target->utrace_flags & _UTRACE_DEATH_EVENTS)) - utrace->stopped = stopped = true; + stopped = true; } else if (task_is_stopped(target)) { /* * Stopped is considered quiescent; when it wakes up, it will From oleg at redhat.com Wed Aug 26 17:31:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 26 Aug 2009 19:31:51 +0200 Subject: [PATCH 2/3] utrace_do_stop: cleanup the usage of ->siglock Message-ID: <20090826173151.GA28831@redhat.com> The unconditional spin_lock(->siglock) looks a bit ugly. We can microoptimize the code and take it only when neede. Imho, also makes the code a little bit more understandable. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~6_DO_STOP_SIGLOCK 2009-08-26 16:53:49.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-26 18:03:36.000000000 +0200 @@ -660,7 +660,6 @@ static bool utrace_do_stop(struct task_s { bool stopped = false; - spin_lock_irq(&target->sighand->siglock); if (unlikely(target->exit_state)) { /* * On the exit path, it's only truly quiescent @@ -674,13 +673,16 @@ static bool utrace_do_stop(struct task_s * Stopped is considered quiescent; when it wakes up, it will * go through utrace_finish_jctl() before doing anything else. */ - __set_task_state(target, TASK_TRACED); - utrace->stopped = stopped = true; + spin_lock_irq(&target->sighand->siglock); + if (likely(task_is_stopped(target))) { + __set_task_state(target, TASK_TRACED); + utrace->stopped = stopped = true; + } + spin_unlock_irq(&target->sighand->siglock); } else if (!utrace->report && !utrace->interrupt) { utrace->report = 1; set_notify_resume(target); } - spin_unlock_irq(&target->sighand->siglock); return stopped; } From oleg at redhat.com Wed Aug 26 17:31:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 26 Aug 2009 19:31:54 +0200 Subject: [PATCH 3/3] utrace_do_stop: move "if (exit_state)" logic to the caller Message-ID: <20090826173154.GA28834@redhat.com> (I am trying to cleanup this code and make it more understandable, but of course this is subjective). utrace_do_stop() considers the dead task without _UTRACE_DEATH_EVENTS as quiescent. This is correct, but - this is only needed for UTRACE_DETACH case - this _looks_ racy, ->exit_state is not protected - it is not immediately obvious this check also relies on utrace_control_dead() which was already called by our caller. - utrace_control_dead() if fact has already verified it is safe to detach. Even if _UTRACE_DEATH_EVENTS are set, we know that utrace_report_death/utrace_release_task can not be called until we drop utrace->lock (or utrace_report_death was already called). In any case it is safe to detach, we can't race with our quiesce/death/reap callbacks. Also, I tried to document "if (exit_state)" check in utrace_control. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~7_DO_STOP_NO_EXIT_STATE 2009-08-26 18:03:36.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-26 19:22:02.000000000 +0200 @@ -660,15 +660,7 @@ static bool utrace_do_stop(struct task_s { bool stopped = false; - if (unlikely(target->exit_state)) { - /* - * On the exit path, it's only truly quiescent - * if it has already been through - * utrace_report_death(), or never will. - */ - if (!(target->utrace_flags & _UTRACE_DEATH_EVENTS)) - stopped = true; - } else if (task_is_stopped(target)) { + if (task_is_stopped(target)) { /* * Stopped is considered quiescent; when it wakes up, it will * go through utrace_finish_jctl() before doing anything else. @@ -1073,17 +1065,24 @@ int utrace_control(struct task_struct *t if (unlikely(IS_ERR(utrace))) return PTR_ERR(utrace); - if (target->exit_state) { + resume = utrace->stopped; + ret = 0; + + /* + * ->exit_state can change under us, this doesn't matter. + * We do not care about ->exit_state in fact, but we do + * care about ->reap and ->death. If either flag is set, + * we must also see ->exit_state != 0. + */ + if (unlikely(target->exit_state)) { ret = utrace_control_dead(target, utrace, action); if (ret) { spin_unlock(&utrace->lock); return ret; } + resume = true; } - resume = utrace->stopped; - ret = 0; - clear_engine_wants_stop(engine); switch (action) { case UTRACE_STOP: From ananth at in.ibm.com Thu Aug 27 06:18:46 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Thu, 27 Aug 2009 11:48:46 +0530 Subject: [PATCH 2] utrace-ptrace-mini: introduce the empty ptrace_utrace_ops In-Reply-To: <20090825165244.GA19097@redhat.com> References: <20090825165244.GA19097@redhat.com> Message-ID: <20090827061846.GA7220@in.ibm.com> On Tue, Aug 25, 2009 at 06:52:44PM +0200, Oleg Nesterov wrote: ... > void exit_ptrace(struct task_struct *tracer) > { > - struct task_struct *p, *n; > - LIST_HEAD(ptrace_dead); > - > - write_lock_irq(&tasklist_lock); > - list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) { > - if (__ptrace_detach(tracer, p)) > - list_add(&p->ptrace_entry, &ptrace_dead); > - } > - write_unlock_irq(&tasklist_lock); > + for (;;) { > + struct task_struct *tracee = NULL; > > - BUG_ON(!list_empty(&tracer->ptraced)); > + read_lock(&tasklist_lock); > + if (!list_empty(&tracer->ptraced)) { > + tracee = list_first_entry(&tracer->ptraced, > + struct task_struct, ptrace_entry); > + get_task_struct(tracee); > + } > + read_unlock(&tasklist_lock); > + if (!tracee) > + break; Can tracee be NULL? If so, get_task_struct() shouldn't be called unconditionally above. Ananth From oleg at redhat.com Thu Aug 27 08:48:34 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 27 Aug 2009 10:48:34 +0200 Subject: [PATCH 2] utrace-ptrace-mini: introduce the empty ptrace_utrace_ops In-Reply-To: <20090827061846.GA7220@in.ibm.com> References: <20090825165244.GA19097@redhat.com> <20090827061846.GA7220@in.ibm.com> Message-ID: <20090827084834.GA3026@redhat.com> On 08/27, Ananth N Mavinakayanahalli wrote: > > On Tue, Aug 25, 2009 at 06:52:44PM +0200, Oleg Nesterov wrote: > > ... > > > void exit_ptrace(struct task_struct *tracer) > > { > > - struct task_struct *p, *n; > > - LIST_HEAD(ptrace_dead); > > - > > - write_lock_irq(&tasklist_lock); > > - list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) { > > - if (__ptrace_detach(tracer, p)) > > - list_add(&p->ptrace_entry, &ptrace_dead); > > - } > > - write_unlock_irq(&tasklist_lock); > > + for (;;) { > > + struct task_struct *tracee = NULL; > > > > - BUG_ON(!list_empty(&tracer->ptraced)); > > + read_lock(&tasklist_lock); > > + if (!list_empty(&tracer->ptraced)) { > > + tracee = list_first_entry(&tracer->ptraced, > > + struct task_struct, ptrace_entry); > > + get_task_struct(tracee); > > + } > > + read_unlock(&tasklist_lock); > > + if (!tracee) > > + break; > > Can tracee be NULL? If so, get_task_struct() shouldn't be called > unconditionally above. tracee == NULL when list_empty(->ptraced) == T. get_task_struct() is called when we know we do have tracees, if (!list_empty()) { tracee = list_first_entry(); get_task_struct(tracee); } in that case tracee != NULL Oleg. From info at lalettredumd.com Thu Aug 27 10:15:00 2009 From: info at lalettredumd.com (=?ISO-8859-1?Q?Nuba?=) Date: Thu, 27 Aug 2009 12:15:00 +0200 Subject: =?iso-8859-1?q?AUDIO_+_WEB_Conf=E9rence_=3D_moins_de_d=E9placeme?= =?iso-8859-1?q?nts_=3D_+_d=27=E9conomies?= Message-ID: An HTML attachment was scrubbed... URL: From info at canal-direct.com Thu Aug 27 15:55:00 2009 From: info at canal-direct.com (=?ISO-8859-1?Q?Canal_Direct?=) Date: Thu, 27 Aug 2009 17:55:00 +0200 Subject: =?iso-8859-1?q?Livraison_sp=E9ciale_pour?= Message-ID: An HTML attachment was scrubbed... URL: From ssc at sscsoluzioni24.it Thu Aug 27 15:37:04 2009 From: ssc at sscsoluzioni24.it (SSC Srl) Date: Thu, 27 Aug 2009 17:37:04 +0200 Subject: ECCO UNA VERA, GRANDE OPPORTUNITA'! Message-ID: <20090827155422.3747.1095550206.swift@192.168.5.5> An HTML attachment was scrubbed... URL: From news at news.bloodservers.com Thu Aug 27 16:57:59 2009 From: news at news.bloodservers.com (admin) Date: Thu, 27 Aug 2009 11:57:59 -0500 Subject: Take a break from your FPS and try Evony! Message-ID: <35024feab9626c7f5e539d41afcf620f@news.bloodservers.com> If you like games like Civilization you'll love this. Free to play Forever! World's Best Web Game Join a global community of millions Instant access, no installation Play anywhere via your browser Build up to 10 cities and conquer the land 220+ quests, hundreds of items & techs Regular content updates Evony is a massively multiplayer online real time strategy game (MMORTS). It is highly popular because it is a persistent world. The landscape does not change each game or each time you log in, but rather you control your fledgling kingdom and direct its affairs. Your subjects will continue building, gathering, researching and laboring even while you are away. You may complete quests, attack barbarians or rival players, form alliances, achieve rank and title and expand your kingdom. Raise your Prestige and vanquish your foes. Your destiny is in your hands. Play for FREE now! -- If you do not want to receive any more newsletters, http://news.bloodservers.com/phplist/lt.php?id=YhgIBlFSDVcETwxLUFIEBw4B To update your preferences and to unsubscribe visit http://news.bloodservers.com/phplist/lt.php?id=YhgIBlFSDVcLTwxLUFIEBw4B Forward a Message to Someone http://news.bloodservers.com/phplist/lt.php?id=YhgIBlFSDVcKTwxLUFIEBw4B -- Powered by PHPlist, www.phplist.com -- -------------- next part -------------- An HTML attachment was scrubbed... URL: From phylae at g-mundt.de Thu Aug 27 18:45:42 2009 From: phylae at g-mundt.de (Pocasangre) Date: Thu, 27 Aug 2009 21:45:42 +0300 Subject: ve Thy Message-ID: <4A96D12B.7070705@g-mundt.de> N started young Tam Lin, Says, 'Lady, thou's pu' nae mae. 6. 'Why pu's thou the rose, Janet, And why breaks thou the wand? Or why comes thou to Carterhaugh Withoutten my command?' 7. 'Carterhaugh, it is my ain, My daddie gave it me; I'll come and gang by Carterhaugh, And ask nae leave at thee.' ... ... ... 8. Janet has kilted her green kirtle A little aboon her knee, And she has snooded her yellow hair A little aboon her bree, And she is to her father's ha', As fast as she can hie. 9. Four and twenty ladies fair Were playing at the ba', And out then cam' the fair Janet, Ance the flower amang them a'. 10. Four and twenty ladies fair Were playing at the chess, And out then cam' the fair Janet, As green as onie glass. 11. Out then spak an auld grey knight, Lay o'er the castle wa', And says, 'Alas, fair Janet, for thee But we'll be blamed a'.' 12. 'Haud your tongue, ye auld fac'd knight, Some ill death may ye die! Father my bairn on whom I will, I'll father nane on thee.' 13. Out then spak her father dear, And he spak meek and mild; 'And ever alas, sweet Janet,' he says, 'I think thou gaes wi' child.' 14. 'If that I gae wi' child, father, Mysel' maun bear the blame; There's ne'er a laird about your ha' Shall get the bairn's n -------------- next part -------------- A non-text attachment was scrubbed... Name: ipoh.jpg Type: image/jpeg Size: 8910 bytes Desc: not available URL: From embrocation at egtenboer.nl Fri Aug 28 11:40:07 2009 From: embrocation at egtenboer.nl (Hakkila) Date: Fri, 28 Aug 2009 13:40:07 +0200 Subject: In this matter. It is certainly not as Message-ID: <4A97BF76.7010306@egtenboer.nl> At all, I had done so merely as a blind. At least they did not take me for a thief as well as a murderer. If the money is really missing, it was for its sake he was murdered I suppose." "Yes, that would be natural," said Muller. "And you know nothing of any other relations or connections that the man may have had? Anything that might give us a clue to the truth?" "No, nothing. He stood so alone here, as far as I knew. Of course, as I told you, his actions of the evening before having been so peculiar--and as I knew that he was not in the happiest frame of mind--I naturally thought of suicide at once, when they told me that he had been found shot dead. Then they told me that the appearance of the room and many other things, proved suicide to have been out of the question. I know nothing more about it. I cannot think any more about it. I know only that I am here in danger of being sentenced for the crime that I never committed--that is enough to keep any man's mind busy." He leaned back with an intense fatigue in every line of his face and figure. Muller rose from -------------- next part -------------- A non-text attachment was scrubbed... Name: eftsoons.jpg Type: image/jpeg Size: 9554 bytes Desc: not available URL: From vendace at aimsys.nl Sat Aug 29 03:31:55 2009 From: vendace at aimsys.nl (Vantuyle Olubunmi) Date: Sat, 29 Aug 2009 05:31:55 +0200 Subject: Nts engaged in the agreeable relaxation of ta Message-ID: <4A989EA8.8040208@aimsys.nl> Ermit her to correspond with me, I have already written to him on the risk to which he submits his daughter in this ominous marriage, but I received neither notice of, nor reply to my letter. Oh, no; the dear girl is unquestionably doomed. I thinks however, I shall write a few lines in reply to this," she added, "but, alas the day! they cannot speak of comfort." Whilst she is thus engaged, we will take, a peep at the on-goings of Dandy and Nancy Gallaher, in the kitchen, where, in pursuance of his message our bashful valet was corroborating, by very able practice, the account which he had given of the talents he had eulogized so justly. "Well, in troth," said he, "but, first and foremost, I haven't the pleasure of knowin' yer name." "Nancy Gallaher's my name, then," she replied. "Ah," said Dandy, suspending the fork and an immense piece of ham on the top of it at the Charybdis which he had opened to an unusual extent to receive it; "ah, ma'am, it wasn't always that, I'll go bail. My counthrymen knows the value of such a purty woman not to stamp some of their names upon her. Not that you have a married look, either, any more than myself; you're too fresh for that, now that I look at you again." A certain cloud, which, as Dandy could perceive, was beginning to darken her countenance, suggested the quick turn of his last observation. The countenance, however, cleared again, and she replied, "It is my name, and what is more, I never changed it. I was hard to plaise--and I am hard to plaise, and ever an' always had a dread of gettin' into bad company, especially when I knew that the same bad company was to last fo -------------- next part -------------- A non-text attachment was scrubbed... Name: sacheted.jpg Type: image/jpeg Size: 9121 bytes Desc: not available URL: From alimentative at mjmnaaijkens.nl Sat Aug 29 16:54:54 2009 From: alimentative at mjmnaaijkens.nl (Hundt Zamborano) Date: Sat, 29 Aug 2009 18:54:54 +0200 Subject: on my morning ride." "Stay a moment," Message-ID: <4A995A83.5070309@mjmnaaijkens.nl> Continental doings. The African feats are almost too many to enumerate. In a "Sortie of the Arab Garrison of Constantine," the Duke de Nemours is made to figure in person. Then we have the Troops of Assault receiving the Signal to leave the Trenches, and "The Scaling of the Breach." There are the "Occupation of the Defile of Teniah," "Combat of the Habrah, of the Sickak, of Samah, of Afzoum." In fine, there is the largest canvass in existence, it is said, the "Taking of the Smalah," that renowned occasion when the army was so _very near_ taking Abd-el-Kader; and the "Battle of Isly," which gained that splendid trophy, the parasol of command. Besides these great subjects there are decorations of military trophies and allegorical figures, which seem to have been painted by some pupil of Vernet. These battles were first of all exhibited to the admiration of Paris in the various salons after their execution, and were then sent off to decorate Versailles. There are also, in the _Gallery of French History_, at Versailles, several others of his, such as the "Battle of Bouvines;" "Charles X. reviewing the National Guard;" the "Marshal St. Cyr," and some others among those we have already named. In them the qualities of the artist are manifested more fully, we think, than in any others of his works. They are full of that energy, vivacity, and daguerreotypi -------------- next part -------------- A non-text attachment was scrubbed... Name: illyricum.jpg Type: image/jpeg Size: 8921 bytes Desc: not available URL: From davidp at mahindra.com Sat Aug 29 23:58:02 2009 From: davidp at mahindra.com (Peg Glass) Date: Sat, 29 Aug 2009 18:58:02 -0500 Subject: Show her your passion Message-ID: <20090829185802.9030603@mahindra.com> Time to stop shying and start increasing the drive. http://bjilj.thyrwanku.com/ From info at estilus.eu Sun Aug 30 02:59:40 2009 From: info at estilus.eu (estilus.eu) Date: Sun, 30 Aug 2009 03:59:40 +0100 Subject: =?iso-8859-1?q?Est=E3o_abertas_v=E1rias_insri=E7=F5es_para_casti?= =?iso-8859-1?q?ng!?= Message-ID: Ola, Est?o abertas v?rias inscri??es para casting na sua cidade! Para vosso conhecimento e respectiva distribui??o. Verifique as v?rias oportunidades abertas neste momento, http://www.estilus.eu/promo/index.php?em=wqw&email=dXRyYWNlLWRldmVsQHJlZGhhdC5jb20= Obrigado pelo tempo disponibilizado. Equipa Estilus Portugal -------------- next part -------------- A non-text attachment was scrubbed... Name: Type: image/jpeg Size: 114791 bytes Desc: not available URL: From pencillers at littlebunny.nl Sun Aug 30 10:11:55 2009 From: pencillers at littlebunny.nl (Osmun) Date: Sun, 30 Aug 2009 12:11:55 +0200 Subject: E to ascend the tower. "At once, " was the answer. The sexton took a Message-ID: <4A9A5042.4080809@littlebunny.nl> stand of the cab we are looking for. The man who hired it evidently arrived on the 6:30 train at the West Station--I have reason to believe that he does not live here,--and then took the street car to this corner. The last ticket is marked for yesterday. In the car he probably made his plans to hire a cab. So you had better stay along the line of th -------------- next part -------------- A non-text attachment was scrubbed... Name: marcher.jpg Type: image/jpeg Size: 8994 bytes Desc: not available URL: From cornel at upload-ro.ro Sun Aug 30 18:28:28 2009 From: cornel at upload-ro.ro (cornel) Date: Sun, 30 Aug 2009 21:28:28 +0300 Subject: cursuri online GRATUITE Message-ID: <20090828.BQPUEJUUZOOUOXOM@upload-ro.ro> An HTML attachment was scrubbed... URL: From oleg at redhat.com Sun Aug 30 18:59:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 30 Aug 2009 20:59:52 +0200 Subject: [PATCH] utrace: check QUIESCE before reporting UTRACE_SIGNAL_REPORT/HANDLER Message-ID: <20090830185952.GA3595@redhat.com> When utrace_get_signal() is called with interrupt || report || signal_handler, it sets event = 0 and, unless UTRACE_SIGNAL_IGN, does the reporting. However this is meaningless without QUIESCE in ->utrace_flags, list_for_each_entry() will check "want & QUIESCE" anyway. I noticed this during the testing, sometimes utrace_get_signal() returns signr != 0 even if there are no engines with ->flag != 0. Correct, but imho is not very clear. Signed-off-by: Oleg Nesterov --- __UTRACE/kernel/utrace.c~8_UGS_CK_QUIESCE 2009-08-26 19:22:02.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-08-30 20:45:41.000000000 +0200 @@ -1939,7 +1939,8 @@ int utrace_get_signal(struct task_struct spin_unlock(&utrace->lock); - if (unlikely(report.result == UTRACE_SIGNAL_IGN)) + if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE)) || + unlikely(report.result == UTRACE_SIGNAL_IGN)) /* * We only got here to clear utrace->signal_handler. */ From buttonmould at in-cyclo.com Sun Aug 30 21:24:28 2009 From: buttonmould at in-cyclo.com (Budworth) Date: Sun, 30 Aug 2009 18:24:28 -0300 Subject: lancthon to, 51. Message-ID: <4A9AEC34.7060308@in-cyclo.com> and those who, differing in some points, know one Master and one service. People on earth will always differ in their opinions. The truth will gain by giving free scope to investigation, and by the illustration of the different sides of the same question." This position is true, and creditable alike to the head and the heart of the author. Church government and doctrine are topics of primary importance to the prosperity of the kingdom of the Redeemer, and no reason can be assigned why they cannot be debated to the edification of the church, except the human frailty of disputants. Had these subjects been discussed in our religious papers with calmness, and in a Christian spirit, they would have been alike instructive and edifying both to ministers and laity. The discussion would have infused into laymen a deeper interest for the welfare of the church, and a larger liberality in the support of her institutions. Are we not commanded to prove all things, and hold fast that which is good; and to be always ready to give to him that asked us a reason for the hope that is in us? But let us not despond; God will overrule even these controversies to the good of his church. _Forsan et haec olim meminisse juvabit._ "The Synods adopting this Platform are e -------------- next part -------------- A non-text attachment was scrubbed... Name: perfecta.jpg Type: image/jpeg Size: 8882 bytes Desc: not available URL: From roland at redhat.com Sun Aug 30 23:52:43 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 30 Aug 2009 16:52:43 -0700 (PDT) Subject: [PATCH] utrace: utrace_finish_vfork: check ->vfork_stop lockless In-Reply-To: Oleg Nesterov's message of Wednesday, 19 August 2009 20:18:51 +0200 <20090819181851.GA26313@redhat.com> References: <20090819180128.GA26296@redhat.com> <20090819181851.GA26313@redhat.com> Message-ID: <20090830235243.0D1DD45B02@magilla.sf.frob.com> > But report/interrupt/etc are all bitfields :1. Doesn't this mean compiler > can do anything it wants with the word where these bitfields live? Can't > it temporary (say) clear ->interrupt while setting ->report ? I think the story on this is that, yes, technically the C standard doesn't rule that sort of thing out, but in reality we know how the compilers and machines ever work and in Linux we already assume this sort of thing. > OK, I think this was a false alarm. But I failed to google the "proof". I don't have any authoritative reference either. Thanks, Roland From roland at redhat.com Mon Aug 31 00:03:24 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 30 Aug 2009 17:03:24 -0700 (PDT) Subject: [PATCH 1/3] utrace_do_stop: don't set ->stopped when ->exit_state In-Reply-To: Oleg Nesterov's message of Wednesday, 26 August 2009 19:31:48 +0200 <20090826173148.GA28823@redhat.com> References: <20090826173148.GA28823@redhat.com> Message-ID: <20090831000324.64C8645B02@magilla.sf.frob.com> > The logic is correct. Just I think it would be tidier to avoid setting > utrace->stopped when the task is dead. It doesn't hurt, but it is not > needed (and _looks_ confusing imho). > > We can just return true, this is enough for the caller. The > In fact, it seems to me "if (exit_state)" case is not needed at all, > see "[PATCH 3/3]". > > Signed-off-by: Oleg Nesterov > > --- __UTRACE/kernel/utrace.c~5_EXIT_STATE_STOPPED 2009-08-26 14:55:51.000000000 +0200 > +++ __UTRACE/kernel/utrace.c 2009-08-26 16:53:49.000000000 +0200 > @@ -668,7 +668,7 @@ static bool utrace_do_stop(struct task_s > * utrace_report_death(), or never will. > */ > if (!(target->utrace_flags & _UTRACE_DEATH_EVENTS)) > - utrace->stopped = stopped = true; > + stopped = true; > } else if (task_is_stopped(target)) { > /* > * Stopped is considered quiescent; when it wakes up, it will > From roland at redhat.com Mon Aug 31 00:09:19 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 30 Aug 2009 17:09:19 -0700 (PDT) Subject: [PATCH 1/3] utrace_do_stop: don't set ->stopped when ->exit_state In-Reply-To: Oleg Nesterov's message of Wednesday, 26 August 2009 19:31:48 +0200 <20090826173148.GA28823@redhat.com> References: <20090826173148.GA28823@redhat.com> Message-ID: <20090831000919.5713F45B02@magilla.sf.frob.com> [Sorry for the bogus reply, finger slipped!] > The logic is correct. Just I think it would be tidier to avoid setting > utrace->stopped when the task is dead. It doesn't hurt, but it is not > needed (and _looks_ confusing imho). > > We can just return true, this is enough for the caller. The theory was that setting the bit would short-circuit future calls. As the code stands, this is also what prevents utrace_set_events() from returning -EINPROGRESS after utrace_control(,,UTRACE_STOP) has returned 0 for the zombie case. [Now responding to 3/3:] > (I am trying to cleanup this code and make it more understandable, but > of course this is subjective). Sure. > utrace_do_stop() considers the dead task without _UTRACE_DEATH_EVENTS > as quiescent. This is correct, but > > - this is only needed for UTRACE_DETACH case Not quite true, as mentioned above. But we can just solve that directly. So I've done that, and then your patches are fine. > - this _looks_ racy, ->exit_state is not protected > > - it is not immediately obvious this check also relies on > utrace_control_dead() which was already called by our > caller. Right. I think this code predates the fix that introduced utrace_control_dead. Thanks, Roland From roland at redhat.com Mon Aug 31 00:17:33 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 30 Aug 2009 17:17:33 -0700 (PDT) Subject: [PATCH 1] utrace-ptrace-mini: get_signal_to_deliver: always call ptrace_signal() In-Reply-To: Oleg Nesterov's message of Tuesday, 25 August 2009 18:52:42 +0200 <20090825165242.GA19094@redhat.com> References: <20090825165242.GA19094@redhat.com> Message-ID: <20090831001733.444F745B02@magilla.sf.frob.com> > No functional changes, preparation. I don't see how this helps prepare for anything in particular. When this path is really relevant at all, we'll just remove ptrace_signal. > Change get_signal_to_deliver() so that ptrace_signal() is called even > if utrace returns signr != 0. > > I think this is more correct now, when ptrace is not implemented on > top of utrace. I don't think so. The return value from tracehook_signal is not a real signal, it's a representative signal directing a specific disposition. If there were both utrace and old ptrace coexisting today, it would be wrong to have ptrace intercept the results of utrace_get_signal. > When we change ptrace to use ->report_signal() ptrace_signal() should > be killed/ifdefed anyway, so afaic this change will not interfere with > utrace-ptrace. There is no other reason to touch this code at all. I don't see any motivation for this patch. Thanks, Roland From roland at redhat.com Mon Aug 31 00:42:31 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 30 Aug 2009 17:42:31 -0700 (PDT) Subject: [PATCH 0/5] utrace-ptrace-mini: rfc hacks In-Reply-To: Oleg Nesterov's message of Tuesday, 25 August 2009 18:52:39 +0200 <20090825165239.GA19086@redhat.com> References: <20090825165239.GA19086@redhat.com> Message-ID: <20090831004231.BD93545B02@magilla.sf.frob.com> > Two questions: > > 1. do you think this _can_ work as a first version of > utrace-ptrace? > > "work" means: could look as utrace-ptrace for 2.6.32, > then we make incremental changes on top. I'm pretty doubtful. I'd like to hear other opinions, and I'm still 100% committed to "whatever works". But this direction doesn't look to me like something that any upstream reviewer would want to see. > This series adds the "fake" ptrace_utrace_ops. We never use these ops, > we only use engine to make stops/wakeups utrace-friendly. I see. This gives it a minimal level of ptrace/utrace cooperation, so it's better than plain utrace alone with the simple ptrace/utrace mutual exclusion logic, only in this one regard. Frankly I do not think that the inability to use utrace and ptrace simlutaneously on a task was significant in the upstream reaction to merging utrace with no ptrace reimplementation. This approach still lacks both a) cleaning up ptrace and b) exercising the utrace API via ptrace. I'm not at all sure this adds anything compelling over just submitting utrace alone and whatever non-ptrace users we could submit. So it's not necessarily bad. But I'm dubious it's of particular benefit to convincing people to merge utrace vs the status quo. My sense of why the ptrace revamp is important to upstream merging is that it demonstrates a) things wind up done more cleanly than before and b) the utrace API is proven adequate for something with well-worn real-world applications and known torture tests. > Signals. ptrace processes a signal after all other attached engines. As my reply to that patch indicated, what you can given the tracehook_get_signal API does not really fit that description. Perhaps by ignoring signr and looking at si_signo you could call it almost that. But still it's questionale. > Why? 2.6.32 is close. I doubt I can make the full-blown (and _working_) > implementation before the merge window. And I am nervous because I doubt. I share your concerns. But all we can do is try to produce things that really will get merged. If you are convinced that efforts on this new temporary kludge approach for ptrace make the difference in getting the utrace core merged into 2.6.32, then go for it. That seems unlikely to me, but I'm far from thinking I know what really does make that difference. Thanks, Roland From roland at redhat.com Mon Aug 31 00:46:50 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 30 Aug 2009 17:46:50 -0700 (PDT) Subject: [PATCH 3] utrace-ptrace-mini: ptrace_stop: make it utrace-friendly In-Reply-To: Oleg Nesterov's message of Tuesday, 25 August 2009 18:52:46 +0200 <20090825165246.GA19100@redhat.com> References: <20090825165246.GA19100@redhat.com> Message-ID: <20090831004650.679CA45B02@magilla.sf.frob.com> > Introduce xxx_utrace_stop() which notifies engine we are going to stop. > It calls report_quiesce(0), but report.action = UTRACE_STOP instead of > UTRACE_RESUME. I don't think this is necessary to go along with the ptrace cooperation hacks. For any engine, there could always be a later engine that returns UTRACE_STOP and causes a stop after you thought the task was going to keep running. If an engine is concerned about that, it uses UTRACE_REPORT and all it knows for sure is that it will get another report after resumption if indeed there was a stop. So all the ptrace hacks need to do is meet that guarantee: set utrace->report when ptrace stops "after" or "between" utrace event points. Thanks, Roland From roland at redhat.com Mon Aug 31 02:46:57 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 30 Aug 2009 19:46:57 -0700 (PDT) Subject: [PATCH] utrace_stop: fix UTRACE_DETACH race In-Reply-To: Oleg Nesterov's message of Wednesday, 26 August 2009 12:27:59 +0200 <20090826102759.GA5455@redhat.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> <20090826102759.GA5455@redhat.com> Message-ID: <20090831024657.0A01B45B02@magilla.sf.frob.com> > I believe the comment and "unlikely" above are not right. > > Neither utrace_control(STOP) nor finish_callback(action => STOP) set > ENGINE_STOP in ->utrace_flags. They change engine->flags only, and > ENGINE_STOP can only "migrate" to ->utrace_flags after utrace_reset(). Right. Let's take a step back, revert commit 00932db and consider the problem case afresh. This flurry of incremental related patches just muddles everything for me. > This case is not unlikely, for example ENGINE_STOP is cleared after the > previous wakeup. We are running, if ENGINE_STOP is set, UTRACE_STOP was > used and utrace_reset() was called after that. Otherwise, _perhaps_ it > was cleared by UTRACE_DETACH. What we want is to change things so that this case *is* unlikely. That is, we really want to avoid any extra O(n) work such as utrace_reset calls. It should never be common to do one of those we don't really want to do. And, all else being equal, when some extra O(n) work is unavoidably required, IMHO it's better that it be in the tracer than in the tracee. I took a different tack and committed these: 96fe3cc Revert "utrace_stop: fix UTRACE_DETACH race" d1a14ce utrace: change UTRACE_STOP bookkeeping 64a8ca3 utrace_reset cleanup Tell me what you think. Thanks, Roland From CastroSelma at msn.com Mon Aug 31 05:51:00 2009 From: CastroSelma at msn.com (Allyson Waller) Date: 31 Aug 2009 07:51:00 +0200 Subject: Listing of small to medium sized businesses for the United States Message-ID: Fields like website, emails address, postal address phone, fax etc.. 1.7 million emails in total on this list - optin - sorted by state Cost just slashed - $293 - from today until this Friday send email to: Winnie at BestAccurateReliable.com Forward email to exit at BestAccurateReliable.com to purge you from our records From oleg at redhat.com Mon Aug 31 13:48:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 31 Aug 2009 15:48:37 +0200 Subject: [PATCH] utrace_stop: fix UTRACE_DETACH race In-Reply-To: <20090831024657.0A01B45B02@magilla.sf.frob.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> <20090826102759.GA5455@redhat.com> <20090831024657.0A01B45B02@magilla.sf.frob.com> Message-ID: <20090831134837.GA11861@redhat.com> On 08/30, Roland McGrath wrote: > > > This case is not unlikely, for example ENGINE_STOP is cleared after the > > previous wakeup. We are running, if ENGINE_STOP is set, UTRACE_STOP was > > used and utrace_reset() was called after that. Otherwise, _perhaps_ it > > was cleared by UTRACE_DETACH. > > What we want is to change things so that this case *is* unlikely. That is, > we really want to avoid any extra O(n) work such as utrace_reset calls. It > should never be common to do one of those we don't really want to do. And, > all else being equal, when some extra O(n) work is unavoidably required, > IMHO it's better that it be in the tracer than in the tracee. Yes, agreed. > I took a different tack and committed these: > > 96fe3cc Revert "utrace_stop: fix UTRACE_DETACH race" > d1a14ce utrace: change UTRACE_STOP bookkeeping > 64a8ca3 utrace_reset cleanup I think this should work, but I'd like to re-read these changes carefully, this all is subtle. And, at first glance, we need something like the patch below. Because now utrace_control(UTRACE_DETACH) does case UTRACE_DETACH: ... if (engine_wants_stop(engine)) resume = true; OK, we need to call utrace_reset() to recalc ->utrace_flags. But utrace_reset() assumes it is safe to play with utrace->attached list, now this is not true. IOW, with this patch utrace_control(UTRACE_DETACH)->utrace_reset() can race with REPORT_CALLBACKS/etc which does list_for_each_entry(->attached). (minor, but perhaps resume should be renamed to "bool reset") "task != current" before utrace_wakeup() doesn't look right too, I think we should check ->stopped instead. Harmless, but otherwise we can call wakeup() while it is not needed. Oleg. --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -722,11 +722,12 @@ static bool utrace_reset(struct task_str __releases(utrace->lock) { struct utrace_engine *engine, *next; + bool xxx = (utrace->stopped || task == current); unsigned long flags = 0; LIST_HEAD(detached); - splice_attaching(utrace); - + if (xxx) + splice_attaching(utrace); /* * Update the set of events of interest from the union * of the interests of the remaining tracing engines. @@ -734,7 +735,7 @@ static bool utrace_reset(struct task_str * We'll collect them on the detached list. */ list_for_each_entry_safe(engine, next, &utrace->attached, entry) { - if (engine->ops == &utrace_detached_ops) { + if (xxx && engine->ops == &utrace_detached_ops) { engine->ops = NULL; list_move(&engine->entry, &detached); } else { @@ -765,7 +766,7 @@ static bool utrace_reset(struct task_str */ utrace->interrupt = utrace->report = utrace->signal_handler = 0; - if (!(flags & ENGINE_STOP) && task != current) + if (!(flags & ENGINE_STOP) && utrace->stopped) /* * No more engines want it stopped. Wake it up. */ From oleg at redhat.com Mon Aug 31 14:30:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 31 Aug 2009 16:30:37 +0200 Subject: [PATCH 0/5] utrace-ptrace-mini: rfc hacks In-Reply-To: <20090831004231.BD93545B02@magilla.sf.frob.com> References: <20090825165239.GA19086@redhat.com> <20090831004231.BD93545B02@magilla.sf.frob.com> Message-ID: <20090831143037.GB11861@redhat.com> On 08/30, Roland McGrath wrote: > > > Signals. ptrace processes a signal after all other attached engines. > > As my reply to that patch indicated, what you can given the > tracehook_get_signal API does not really fit that description. Yes. > Perhaps by ignoring signr and looking at si_signo you could > call it almost that. But still it's questionale. Yes. And the usage of "ka" is buggy. Perhaps more or less solveable, but questionale. > > Why? 2.6.32 is close. I doubt I can make the full-blown (and _working_) > > implementation before the merge window. And I am nervous because I doubt. > > I share your concerns. But all we can do is try to produce things that > really will get merged. If you are convinced that efforts on this new > temporary kludge approach for ptrace make the difference in getting the > utrace core merged into 2.6.32, then go for it. That seems unlikely to me, Now this seems unlikely to me too. I had to do a lot of testing on Sunday before I was able to realize we have other issues. For example, utrace_reset() clears TIF_SYSCALL_TRACE. Again, looks fixeable, but uglifies this kludge even more. Oleg. From oleg at redhat.com Mon Aug 31 14:39:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 31 Aug 2009 16:39:30 +0200 Subject: [PATCH 3] utrace-ptrace-mini: ptrace_stop: make it utrace-friendly In-Reply-To: <20090831004650.679CA45B02@magilla.sf.frob.com> References: <20090825165246.GA19100@redhat.com> <20090831004650.679CA45B02@magilla.sf.frob.com> Message-ID: <20090831143930.GC11861@redhat.com> On 08/30, Roland McGrath wrote: > > > Introduce xxx_utrace_stop() which notifies engine we are going to stop. > > It calls report_quiesce(0), but report.action = UTRACE_STOP instead of > > UTRACE_RESUME. > > I don't think this is necessary to go along with the ptrace cooperation > hacks. For any engine, there could always be a later engine that returns > UTRACE_STOP and causes a stop after you thought the task was going to keep > running. If an engine is concerned about that, it uses UTRACE_REPORT and > all it knows for sure is that it will get another report after resumption > if indeed there was a stop. So all the ptrace hacks need to do is meet > that guarantee: set utrace->report when ptrace stops "after" or "between" > utrace event points. Yes. But this hack was needed because ptrace_utrace_ops is empty, it doesn't even have ->report_quiesce which could return UTRACE_STOP. So xxx_utrace_stop() just sets report.action = UTRACE_STOP "in advance" and then notifies other engines. But this doesn't matter, I no longer think this all makes sense. Oleg. From oleg at redhat.com Mon Aug 31 16:04:14 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 31 Aug 2009 18:04:14 +0200 Subject: [PATCH] utrace_stop: fix UTRACE_DETACH race In-Reply-To: <20090831134837.GA11861@redhat.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> <20090826102759.GA5455@redhat.com> <20090831024657.0A01B45B02@magilla.sf.frob.com> <20090831134837.GA11861@redhat.com> Message-ID: <20090831160414.GA18860@redhat.com> Btw, is it allowed to use utrace_control(UTRACE_DETACH) from ->report_any() ? If yes, then we need a bit more fixes... On 08/31, Oleg Nesterov wrote: > > On 08/30, Roland McGrath wrote: > > > > > This case is not unlikely, for example ENGINE_STOP is cleared after the > > > previous wakeup. We are running, if ENGINE_STOP is set, UTRACE_STOP was > > > used and utrace_reset() was called after that. Otherwise, _perhaps_ it > > > was cleared by UTRACE_DETACH. > > > > What we want is to change things so that this case *is* unlikely. That is, > > we really want to avoid any extra O(n) work such as utrace_reset calls. It > > should never be common to do one of those we don't really want to do. And, > > all else being equal, when some extra O(n) work is unavoidably required, > > IMHO it's better that it be in the tracer than in the tracee. > > Yes, agreed. > > > I took a different tack and committed these: > > > > 96fe3cc Revert "utrace_stop: fix UTRACE_DETACH race" > > d1a14ce utrace: change UTRACE_STOP bookkeeping > > 64a8ca3 utrace_reset cleanup > > I think this should work, but I'd like to re-read these changes carefully, > this all is subtle. And, at first glance, we need something like the patch > below. > > Because now utrace_control(UTRACE_DETACH) does > > case UTRACE_DETACH: > ... > if (engine_wants_stop(engine)) > resume = true; > > OK, we need to call utrace_reset() to recalc ->utrace_flags. But utrace_reset() > assumes it is safe to play with utrace->attached list, now this is not true. > IOW, with this patch utrace_control(UTRACE_DETACH)->utrace_reset() can race > with REPORT_CALLBACKS/etc which does list_for_each_entry(->attached). > (minor, but perhaps resume should be renamed to "bool reset") > > "task != current" before utrace_wakeup() doesn't look right too, I think we > should check ->stopped instead. Harmless, but otherwise we can call wakeup() > while it is not needed. > > Oleg. > > --- a/kernel/utrace.c > +++ b/kernel/utrace.c > @@ -722,11 +722,12 @@ static bool utrace_reset(struct task_str > __releases(utrace->lock) > { > struct utrace_engine *engine, *next; > + bool xxx = (utrace->stopped || task == current); > unsigned long flags = 0; > LIST_HEAD(detached); > > - splice_attaching(utrace); > - > + if (xxx) > + splice_attaching(utrace); > /* > * Update the set of events of interest from the union > * of the interests of the remaining tracing engines. > @@ -734,7 +735,7 @@ static bool utrace_reset(struct task_str > * We'll collect them on the detached list. > */ > list_for_each_entry_safe(engine, next, &utrace->attached, entry) { > - if (engine->ops == &utrace_detached_ops) { > + if (xxx && engine->ops == &utrace_detached_ops) { > engine->ops = NULL; > list_move(&engine->entry, &detached); > } else { > @@ -765,7 +766,7 @@ static bool utrace_reset(struct task_str > */ > utrace->interrupt = utrace->report = utrace->signal_handler = 0; > > - if (!(flags & ENGINE_STOP) && task != current) > + if (!(flags & ENGINE_STOP) && utrace->stopped) > /* > * No more engines want it stopped. Wake it up. > */ From roland at redhat.com Mon Aug 31 19:17:52 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 31 Aug 2009 12:17:52 -0700 (PDT) Subject: [PATCH] utrace_stop: fix UTRACE_DETACH race In-Reply-To: Oleg Nesterov's message of Monday, 31 August 2009 18:04:14 +0200 <20090831160414.GA18860@redhat.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> <20090826102759.GA5455@redhat.com> <20090831024657.0A01B45B02@magilla.sf.frob.com> <20090831134837.GA11861@redhat.com> <20090831160414.GA18860@redhat.com> Message-ID: <20090831191752.19AEB45B02@magilla.sf.frob.com> > Btw, is it allowed to use utrace_control(UTRACE_DETACH) from ->report_any() ? > If yes, then we need a bit more fixes... It's kind of a stupid thing to do, but yes, it should be allowed. I think it's fine either if it always returns -EINPROGRESS or if it returns 0 for the target==current case. It doesn't have to be handled optimally, but it should have about the same semantics as returning UTRACE_DETACH from the callback. (The differences being that later utrace_* calls inside that callback could return -ESRCH.) Thanks, Roland From roland at redhat.com Mon Aug 31 19:38:28 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 31 Aug 2009 12:38:28 -0700 (PDT) Subject: [PATCH] utrace_stop: fix UTRACE_DETACH race In-Reply-To: Oleg Nesterov's message of Monday, 31 August 2009 15:48:37 +0200 <20090831134837.GA11861@redhat.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> <20090826102759.GA5455@redhat.com> <20090831024657.0A01B45B02@magilla.sf.frob.com> <20090831134837.GA11861@redhat.com> Message-ID: <20090831193828.35A9845B02@magilla.sf.frob.com> > I think this should work, but I'd like to re-read these changes carefully, > this all is subtle. Sure. I meant it as a proposal for you to consider. I didn't think through all the corners myself. It just seemed easier to do those commits as the starting point for further discussion than to describe the plan and ask you to implement it. > OK, we need to call utrace_reset() to recalc ->utrace_flags. But utrace_reset() > assumes it is safe to play with utrace->attached list, now this is not true. Yes, that is right. > IOW, with this patch utrace_control(UTRACE_DETACH)->utrace_reset() can race > with REPORT_CALLBACKS/etc which does list_for_each_entry(->attached). > (minor, but perhaps resume should be renamed to "bool reset") Yes, that is probably clearer. > "task != current" before utrace_wakeup() doesn't look right too, I think we > should check ->stopped instead. Harmless, but otherwise we can call wakeup() > while it is not needed. Ok. I think I was concerned about ->stopped not always being right. But I think you're right that it should be. It should not ever be set on current. Please review commit c36a311. Thanks, Roland From desexualize at pieterjan.com Tue Sep 1 04:53:20 2009 From: desexualize at pieterjan.com (Tinn) Date: Tue, 01 Sep 2009 05:53:20 +0100 Subject: Hoffs Message-ID: <4A9CA762.4010409@pieterjan.com> E always heading south and appear to be in a powerful hurry, but the funny part of it is I ain't never seen them coming back." "Do you know their names?" "No, I can't say I do, though it seems as if I'd heard one of them called Fred. I can't say which it was." "Do they always come by on the same day--on Wednesday?" asked Jane, forgetful once more of Dean's warning to let him do the talking lest her voice should betray her sex. "Come to think of it," said the man, apparently noticing nothing unusual, "I guess it always is on a Wednesday they come by." "Is the number of their car anything like this?" asked Dean, exhibiting an entry in his notebook. "I couldn't say," said the man, studying the figures. "I know it is a New York license, and the number ends with two nines like this one does. What might you be wanting them for?" He spoke to a cloud of dust, for Dean had started up the motorcycle before he finished speaking and already was speeding away. "Where now?" asked Jane. "I don't know," he answered frankly, "I only know we are going the direction the Hoffs went, and I want to gain on them before they get too far ahead. The chap back there had told us all he knew and was beginning to get curious, so I thought it better to vamoose." "It's funny about his never seeing them coming back." "Probably there is nothing mysterious about that. I have a notion they always come up one side the river and down the other, taking the 125th Street ferry home. That would not be a bad plan to help them in eluding too curious observers. All these German spies are trained to leave as blind a trail behind them as possible. The thing we have got to discover is what brought them up here. We've just got to find out their destination." "I am afraid there is little chance of our doing that," insisted Jane. "We've nothing to go on." "We've learned something. We know that their destination is somewhere between here and Fort Lee on this side of the river. That narrows down the search considerably. That's more, too, than anybody else that the Chief has had on their trail has learned. Something tells me that we are getting warm right now. Obviously the place they come to must -------------- next part -------------- A non-text attachment was scrubbed... Name: hypnotherapy.jpg Type: image/jpeg Size: 9658 bytes Desc: not available URL: From strielkowski at astec-asia.com Tue Sep 1 15:17:46 2009 From: strielkowski at astec-asia.com (Bert Shepherd) Date: Tue, 1 Sep 2009 15:17:46 -0000 Subject: Summer sale on health supply. Message-ID: <20090901151746.2050906@astec-asia.com> Call, meet and sleep with her tonight. http://gfxkxd.sightwild.com/ X-Antivirus: avast! (VPS 090831-0, 2009-08-31), Outbound message X-Antivirus-Status: Clean From oleg at redhat.com Tue Sep 1 18:21:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 1 Sep 2009 20:21:53 +0200 Subject: [PATCH] utrace_stop: fix UTRACE_DETACH race In-Reply-To: <20090831193828.35A9845B02@magilla.sf.frob.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> <20090826102759.GA5455@redhat.com> <20090831024657.0A01B45B02@magilla.sf.frob.com> <20090831134837.GA11861@redhat.com> <20090831193828.35A9845B02@magilla.sf.frob.com> Message-ID: <20090901182153.GA15431@redhat.com> On 08/31, Roland McGrath wrote: > > Please review commit c36a311. I think we need more changes. Please see 3 patches I am going to send. But, Roland, please review. I am already tired, and just can't concentrate. I am sending these patches just because I do not want to delay this discussion. Oleg. From oleg at redhat.com Tue Sep 1 18:22:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 1 Sep 2009 20:22:41 +0200 Subject: [PATCH 1/3] utrace_control: fix utrace_reset(safe) usage when ->exit_state != 0 Message-ID: <20090901182241.GA15629@redhat.com> c36a311e8a6c1bbe6115dc1810ac88344782857c breaks utrace_control_dead() logic. It is important that utrace_reset(safe) is called with "safe = true" when we detach from the dead task. Otherwise, this engine will not be "unlinked" until utrace_release_task(), and given that the dead task can stay in zombie state unpredictably long we have problems: for example, utrace_barrier() will hang. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) --- __UTRACE/kernel/utrace.c~1_FIX_DEAD_DETACH 2009-09-01 19:12:14.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-01 20:02:26.000000000 +0200 @@ -1037,7 +1037,7 @@ int utrace_control(struct task_struct *t enum utrace_resume_action action) { struct utrace *utrace; - bool reset; + bool reset, safe = false; int ret; if (unlikely(action > UTRACE_DETACH)) @@ -1074,7 +1074,7 @@ int utrace_control(struct task_struct *t spin_unlock(&utrace->lock); return ret; } - reset = true; + reset = safe = true; } switch (action) { @@ -1212,8 +1212,8 @@ int utrace_control(struct task_struct *t * there is nothing more we need to do. */ if (reset) - utrace_reset(target, utrace, - utrace->stopped || target == current); + utrace_reset(target, utrace, safe || utrace->stopped || + target == current); else spin_unlock(&utrace->lock); From oleg at redhat.com Tue Sep 1 18:22:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 1 Sep 2009 20:22:44 +0200 Subject: [PATCH 2/3] utrace_control: don't mark_engine_detached() before engine_wants_stop() Message-ID: <20090901182244.GA15632@redhat.com> mark_engine_detached() removes ENGINE_STOP from engine->flags, this means utrace_control(UTRACE_DETACH) can never seer engine_wants_stop() == T. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) --- __UTRACE/kernel/utrace.c~1_FIX_DETACH_BEFORE_WANT_STOP 2009-09-01 20:02:26.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-01 20:03:25.000000000 +0200 @@ -1086,7 +1086,6 @@ int utrace_control(struct task_struct *t break; case UTRACE_DETACH: - mark_engine_detached(engine); reset = reset || utrace_do_stop(target, utrace); if (!reset) { /* @@ -1106,9 +1105,9 @@ int utrace_control(struct task_struct *t * We need utrace_reset() to check if anyone else * still wants this target to stay stopped. */ - clear_engine_wants_stop(engine); reset = true; } + mark_engine_detached(engine); break; case UTRACE_RESUME: From oleg at redhat.com Tue Sep 1 18:22:47 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 1 Sep 2009 20:22:47 +0200 Subject: [PATCH 3/3] utrace_reset: do not use "unsafe mode" Message-ID: <20090901182247.GA15635@redhat.com> Personally I dislike the complications introduced by safe/unsafe modes of utrace_reset(). And I think these complications are not needed. Let's return to the previous discussion: > This case is not unlikely, for example ENGINE_STOP is cleared after the > previous wakeup. We are running, if ENGINE_STOP is set, UTRACE_STOP was > used and utrace_reset() was called after that. Otherwise, _perhaps_ it > was cleared by UTRACE_DETACH. What we want is to change things so that this case *is* unlikely. That is, we really want to avoid any extra O(n) work such as utrace_reset calls. It should never be common to do one of those we don't really want to do. Yes! But with the recent changes mark_engine_wants_stop() adds ENGINE_STOP to ->utrace_flags, this means the case when utrace_stop() calls utrace_reset() is really unlikely. So. Kill this (imho) awful "bool safe" argument. utrace_reset() must be always safe. Instead, - change utrace_control(DETACH) to clear ENGINE_STOP from ->utrace_flags - change utrace_stop() to call utrace_reset() and re-check when there is no ENGINE_STOP in ->utrace_flags. IOW, this partly re-rereverts 00932dbe24bd4273e6d723baa9342e7b3e248911 Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) --- __UTRACE/kernel/utrace.c~2_KILL_SAFE 2009-09-01 20:03:25.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-01 20:07:45.000000000 +0200 @@ -707,22 +707,17 @@ static void utrace_wakeup(struct task_st * some stale bits in @task->utrace_flags. Clean them up and recompute the * flags. Returns true if we're now fully detached. * - * @safe is true if this is a safe point to touch the engine list, - * i.e. @task is either current or known to be stopped. - * * Called with @utrace->lock held, returns with it released. * After this returns, @utrace might be freed if everything detached. */ -static bool utrace_reset(struct task_struct *task, struct utrace *utrace, - bool safe) +static bool utrace_reset(struct task_struct *task, struct utrace *utrace) __releases(utrace->lock) { struct utrace_engine *engine, *next; unsigned long flags = 0; LIST_HEAD(detached); - if (safe) - splice_attaching(utrace); + splice_attaching(utrace); /* * Update the set of events of interest from the union @@ -731,7 +726,7 @@ static bool utrace_reset(struct task_str * We'll collect them on the detached list. */ list_for_each_entry_safe(engine, next, &utrace->attached, entry) { - if (safe && engine->ops == &utrace_detached_ops) { + if (engine->ops == &utrace_detached_ops) { engine->ops = NULL; list_move(&engine->entry, &detached); } else { @@ -789,7 +784,7 @@ static void utrace_stop(struct task_stru * inside this function. It should never be set on entry. */ BUG_ON(utrace->stopped); - +relock: spin_lock(&utrace->lock); if (action == UTRACE_INTERRUPT) { @@ -816,7 +811,9 @@ static void utrace_stop(struct task_stru * steps (this can matter for UTRACE_RESUME but not UTRACE_DETACH). */ if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { - spin_unlock(&utrace->lock); + utrace_reset(task, utrace); + if (task->utrace_flags & ENGINE_STOP) + goto relock; return; } @@ -1037,7 +1034,7 @@ int utrace_control(struct task_struct *t enum utrace_resume_action action) { struct utrace *utrace; - bool reset, safe = false; + bool reset; int ret; if (unlikely(action > UTRACE_DETACH)) @@ -1074,7 +1071,7 @@ int utrace_control(struct task_struct *t spin_unlock(&utrace->lock); return ret; } - reset = safe = true; + reset = true; } switch (action) { @@ -1086,6 +1083,9 @@ int utrace_control(struct task_struct *t break; case UTRACE_DETACH: + if (engine_wants_stop(engine)) + target->utrace_flags &= ~ENGINE_STOP; + mark_engine_detached(engine); reset = reset || utrace_do_stop(target, utrace); if (!reset) { /* @@ -1100,14 +1100,6 @@ int utrace_control(struct task_struct *t if (utrace->reporting == engine) ret = -EINPROGRESS; } - if (engine_wants_stop(engine)) { - /* - * We need utrace_reset() to check if anyone else - * still wants this target to stay stopped. - */ - reset = true; - } - mark_engine_detached(engine); break; case UTRACE_RESUME: @@ -1211,8 +1203,7 @@ int utrace_control(struct task_struct *t * there is nothing more we need to do. */ if (reset) - utrace_reset(target, utrace, safe || utrace->stopped || - target == current); + utrace_reset(target, utrace); else spin_unlock(&utrace->lock); @@ -1318,7 +1309,7 @@ static inline void finish_report_reset(s { if (unlikely(!report->takers || report->detaches)) { spin_lock(&utrace->lock); - if (utrace_reset(task, utrace, true)) + if (utrace_reset(task, utrace)) report->action = UTRACE_RESUME; } } @@ -1741,7 +1732,7 @@ void utrace_report_death(struct task_str */ utrace_reap(task, utrace); else - utrace_reset(task, utrace, true); + utrace_reset(task, utrace); } /* From info at canal-direct.com Wed Sep 2 12:10:00 2009 From: info at canal-direct.com (=?ISO-8859-1?Q?Nuba?=) Date: Wed, 02 Sep 2009 14:10:00 +0200 Subject: =?iso-8859-1?q?Audio_Conf=E9rence_sans_facturation_=3A_Inscripti?= =?iso-8859-1?q?on_gratuite?= Message-ID: An HTML attachment was scrubbed... URL: From cans at somvao.nl Wed Sep 2 15:52:35 2009 From: cans at somvao.nl (Doegg) Date: Wed, 02 Sep 2009 12:52:35 -0300 Subject: ten dollars is a good deal of money for a little boy to earn at Message-ID: <4A9E934C.5020401@somvao.nl> "I suppose we ought to make him run until he is played out," said Bert, "That's the way to cure a horse of running away." But none of the boys felt like risking their bones even to cure Sable, so the panting animal was led to the stable and for the rest of the day allowed to think over his bad conduct. But that was not the last of the runaway, for in the evening just after supper old Mr. Trimble paid a visit to Tom's father. "I came over to tell you what a scallywag of a boy you've got," began the cross old man. "He and a lot of young loafers took a horse and drove him all through my cornfield to-day, and now you've got to pay the damages." "My son is not a scallywag," Mr. Mason declared, "and if you call him names like loafer and scallywag I'll make you pay damages." "Oh! you will, eh?" the other sneered. "Think I'm afraid of an old constable up here, do you?" "Well now, see here," Mr. Mason said, "Be reasonable and do not quarrel over an accident. If any corn is knocked down I'll get Tom to fix it up, if it's broken down we wil -------------- next part -------------- A non-text attachment was scrubbed... Name: annoyances.jpg Type: image/jpeg Size: 10035 bytes Desc: not available URL: From hot-deals at clubvacationdeals.com Wed Sep 2 18:05:29 2009 From: hot-deals at clubvacationdeals.com (Club Vacation Deals) Date: Wed, 2 Sep 2009 14:05:29 -0400 Subject: Come to celebrate the Mexico Independence day Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Sep 2 21:23:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 2 Sep 2009 23:23:49 +0200 Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: <20090824064736.2F3D7414DF@magilla.sf.frob.com> References: <20090814144555.GA28295@redhat.com> <20090818045433.511254730F@magilla.sf.frob.com> <20090818181732.GA17634@redhat.com> <20090818211627.6F0274730F@magilla.sf.frob.com> <20090819135323.GC632@redhat.com> <20090824064736.2F3D7414DF@magilla.sf.frob.com> Message-ID: <20090902212349.GA3953@redhat.com> On 08/23, Roland McGrath wrote: > > > > This model seems like a better fit for ptrace to me. The anchoring data > > > structure is the tracer's tracees list, which links together the > > > ptrace_context structs. A live ptrace_context has an engine pointer and > > > a ref for it. > > > > OK. Not that I really understand this all in details, but OK. > > > > But. Do you think we should do this right now? > > If it is the right way to handle the data structure lifetimes, I don't see > why we would do it any different way first. One of the main points of what > makes one plan or another "the right way" is that it makes it easier to get > the corners right. So if it's easier to get the corners right another way, > then maybe that other way is the right one. > > > I don't. Imho, we need a lot of changes before this. > > I don't understand why you think this. Simple answer. Because I do not know how to implement this. At least now. I tried to think of this more, but I don't see how to make the first steps. (Yes, to be honest, this looks like "unnecessary complication" to me, I have to admit. But this is not the reason.) > > Do you have any suggestion what can we do right now? (assuming you won't > > apply your ops->release patch). > > I didn't say I wouldn't. I was hoping for some more discussion about it > and better understanding of the underlying issues that made you want it, > maybe with some voices other than just yours and mine. Agreed, but nobody else cares ;) So, I am going to use the simple ops->release method for now. Once we have the working code we can reconsider the lifetime rules for engine/ engine->data. Oleg. From oleg at redhat.com Wed Sep 2 21:24:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 2 Sep 2009 23:24:24 +0200 Subject: [PATCH 16-19] mv ptrace options into engine->data Message-ID: <20090902212424.GA4286@redhat.com> Incomplete. The last 2 patches I was going to sent which convert "->ptrace & PT_XXX" checks have stupid bugs, will send tomorrow. Oleg. From oleg at redhat.com Wed Sep 2 21:24:29 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 2 Sep 2009 23:24:29 +0200 Subject: [PATCH 16] introduce the empty struct ptrace_context Message-ID: <20090902212429.GA4293@redhat.com> (relies on 471d6f49e9b9be7830adf1a47f18f5ba90a05041 "utrace_engine_ops: add release hook" in utrace-dtor) Introduce the empty struct ptrace_context, change ptrace_attach_task() to setup engine->data. It should be used for ptrace_set_action() and ptrace_set_stop_event(), the current usage of ->ptrace is racy. Also, ->exit_code and ->last_siginfo should live in engine->data too. Eventually, all ptrace-related members should be moved from task_struct. --- kernel/ptrace.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) --- PU/kernel/ptrace.c~16_PTRACE_CONTEXT 2009-09-02 17:50:58.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-02 19:48:53.000000000 +0200 @@ -24,6 +24,8 @@ #include #include +struct ptrace_context { +}; /* * ptrace a task: make the debugger its new parent and @@ -467,6 +469,11 @@ static u32 ptrace_report_quiesce(u32 act return ptrace_resume_action(task); } +static void ptrace_release(void *data) +{ + kfree(data); +} + static const struct utrace_engine_ops ptrace_utrace_ops = { .report_signal = ptrace_report_signal, .report_quiesce = ptrace_report_quiesce, @@ -475,6 +482,7 @@ static const struct utrace_engine_ops pt .report_clone = ptrace_report_clone, .report_syscall_entry = ptrace_report_syscall_entry, .report_syscall_exit = ptrace_report_syscall_exit, + .release = ptrace_release, }; /* @@ -483,18 +491,24 @@ static const struct utrace_engine_ops pt */ static int ptrace_attach_task(struct task_struct *tracee) { + struct ptrace_context *context; struct utrace_engine *engine; unsigned long events; int err; + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (unlikely(!context)) + return -ENOMEM; + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); + &ptrace_utrace_ops, context); if (unlikely(IS_ERR(engine))) { err = PTR_ERR(engine); if (err != -ESRCH && err != -ERESTARTNOINTR) err = -EPERM; + kfree(context); return err; } /* From oleg at redhat.com Wed Sep 2 21:24:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 2 Sep 2009 23:24:32 +0200 Subject: [PATCH 17] introduce ptrace_context->options Message-ID: <20090902212432.GA4300@redhat.com> Add "int options" into struct ptrace_context. Will be used to hold PT_XXX options. Currently is not used, but: - ptrace_attach_task() has a new argument, "int options". Used by ptrace_clone_attach() which should copy the parent's options - introduce __ptrace_set_options() helper which updates ->options and utrace events mask. - change ptrace_attach_task() to use this new helper. --- kernel/ptrace.c | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) --- PU/kernel/ptrace.c~17_CTX_EVENTS 2009-09-02 19:48:53.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-02 19:53:06.000000000 +0200 @@ -25,8 +25,15 @@ #include struct ptrace_context { + int options; }; +static inline +struct ptrace_context *ptrace_context(struct utrace_engine *engine) +{ + return engine->data; +} + /* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. @@ -41,7 +48,7 @@ void __ptrace_link(struct task_struct *c } static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */ -static int ptrace_attach_task(struct task_struct *tracee); +static int ptrace_attach_task(struct task_struct *tracee, int options); static void ptrace_abort_attach(struct task_struct *tracee); static void ptrace_detach_task(struct task_struct *child, int sig) @@ -216,14 +223,15 @@ static u32 ptrace_report_exit(enum utrac } static void ptrace_clone_attach(struct task_struct *parent, - struct task_struct *child) + struct task_struct *child, + int options) { struct task_struct *tracer; bool abort = true; if (!parent->ptrace) return; - if (unlikely(ptrace_attach_task(child))) { + if (unlikely(ptrace_attach_task(child, options))) { WARN_ON(1); return; } @@ -252,6 +260,7 @@ static u32 ptrace_report_clone(enum utra unsigned long clone_flags, struct task_struct *child) { + struct ptrace_context *context = ptrace_context(engine); int event; if ((clone_flags & CLONE_VFORK) && @@ -289,7 +298,7 @@ static u32 ptrace_report_clone(enum utra * So does CLONE_PTRACE, even with no event to report. */ if (event || (clone_flags & CLONE_PTRACE)) - ptrace_clone_attach(parent, child); + ptrace_clone_attach(parent, child, context->options); if (event) return utrace_ptrace_event(parent, event, child->pid); @@ -485,15 +494,33 @@ static const struct utrace_engine_ops pt .release = ptrace_release, }; +static inline int __ptrace_set_options(struct task_struct *target, + struct utrace_engine *engine, + unsigned long options) +{ + struct ptrace_context *context = ptrace_context(engine); + /* + * We need QUIESCE for resume handling, CLONE to check + * for CLONE_PTRACE, other events are always reported. + */ + unsigned long events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | + UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; + + context->options = options; + if (options & PT_TRACE_EXIT) + events |= UTRACE_EVENT(EXIT); + + return utrace_set_events(target, engine, events); +} + /* * Attach a utrace engine for ptrace and set up its event mask. * Returns error code or 0 on success. */ -static int ptrace_attach_task(struct task_struct *tracee) +static int ptrace_attach_task(struct task_struct *tracee, int options) { struct ptrace_context *context; struct utrace_engine *engine; - unsigned long events; int err; context = kzalloc(sizeof(*context), GFP_KERNEL); @@ -512,16 +539,10 @@ static int ptrace_attach_task(struct tas return err; } /* - * We need QUIESCE for resume handling, CLONE to check - * for CLONE_PTRACE, other events are always reported. - */ - events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | - UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; - /* * It can fail only if the tracee is dead, the caller * must notice this before setting PT_PTRACED. */ - err = utrace_set_events(tracee, engine, events); + err = __ptrace_set_options(tracee, engine, options); WARN_ON(err && !tracee->exit_state); utrace_engine_put(engine); return 0; @@ -634,7 +655,7 @@ int ptrace_attach(struct task_struct *ta if (retval) goto unlock_creds; - retval = ptrace_attach_task(task); + retval = ptrace_attach_task(task, 0); if (unlikely(retval)) goto unlock_creds; @@ -669,7 +690,7 @@ out: int ptrace_traceme(void) { bool detach = true; - int ret = ptrace_attach_task(current); + int ret = ptrace_attach_task(current, 0); if (unlikely(ret)) return ret; From oleg at redhat.com Wed Sep 2 21:24:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 2 Sep 2009 23:24:35 +0200 Subject: [PATCH 18] introduce ptrace_set_options() Message-ID: <20090902212435.GA4303@redhat.com> Introduce ptrace_set_options(). It will replace ptrace_setoptions() but we can't kill the old helper yet. The new one sets ptrace_context->options, but we should convert the code which checks ->ptrace for PT_XXX first. Currently PTRACE_SETOPTIONS calls both helpers. --- kernel/ptrace.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) --- PU/kernel/ptrace.c~18_SET_OPTIONS 2009-09-02 19:53:06.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-02 20:17:34.000000000 +0200 @@ -871,6 +871,7 @@ int ptrace_writedata(struct task_struct return copied; } +/* will die soon ... */ static int ptrace_setoptions(struct task_struct *child, long data) { child->ptrace &= ~PT_TRACE_MASK; @@ -901,6 +902,42 @@ static int ptrace_setoptions(struct task return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; } +static int ptrace_set_options(struct task_struct *child, long data) +{ + struct utrace_engine *engine; + int options = 0; + + if (data & PTRACE_O_TRACESYSGOOD) + options |= PT_TRACESYSGOOD; + + if (data & PTRACE_O_TRACEFORK) + options |= PT_TRACE_FORK; + + if (data & PTRACE_O_TRACEVFORK) + options |= PT_TRACE_VFORK; + + if (data & PTRACE_O_TRACECLONE) + options |= PT_TRACE_CLONE; + + if (data & PTRACE_O_TRACEEXEC) + options |= PT_TRACE_EXEC; + + if (data & PTRACE_O_TRACEVFORKDONE) + options |= PT_TRACE_VFORK_DONE; + + if (data & PTRACE_O_TRACEEXIT) + options |= PT_TRACE_EXIT; + + engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (likely(!IS_ERR(engine))) { + __ptrace_set_options(child, engine, options); + utrace_engine_put(engine); + } + + return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; +} + static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info) { unsigned long flags; @@ -1139,6 +1176,7 @@ int ptrace_request(struct task_struct *c #endif case PTRACE_SETOPTIONS: ret = ptrace_setoptions(child, data); + ret = ptrace_set_options(child, data); break; case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned long __user *) data); From oleg at redhat.com Wed Sep 2 21:24:38 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 2 Sep 2009 23:24:38 +0200 Subject: [PATCH 19] "disable" tracehook_prepare_clone() Message-ID: <20090902212438.GA4310@redhat.com> The most problematic user of "->ptrace & PT_" checks is tracehook_prepare_clone(). I need to re-check this, but iirc this hook is not needed at all since "[PATCH 10] ptrace_report_clone: rework auto-attaching". This patch changes it to always return 0. --- include/linux/tracehook.h | 12 ------------ 1 file changed, 12 deletions(-) --- PU/include/linux/tracehook.h~19_DISABLE_PREPARE_CLONE 2009-08-20 20:09:25.000000000 +0200 +++ PU/include/linux/tracehook.h 2009-09-02 20:30:00.000000000 +0200 @@ -208,18 +208,6 @@ static inline void tracehook_report_exit */ static inline int tracehook_prepare_clone(unsigned clone_flags) { - if (clone_flags & CLONE_UNTRACED) - return 0; - - if (clone_flags & CLONE_VFORK) { - if (current->ptrace & PT_TRACE_VFORK) - return PTRACE_EVENT_VFORK; - } else if ((clone_flags & CSIGNAL) != SIGCHLD) { - if (current->ptrace & PT_TRACE_CLONE) - return PTRACE_EVENT_CLONE; - } else if (current->ptrace & PT_TRACE_FORK) - return PTRACE_EVENT_FORK; - return 0; } From speedpro at bol.com.br Thu Sep 3 04:43:38 2009 From: speedpro at bol.com.br (Fabiane Menezes) Date: Thu, 3 Sep 2009 04:43:38 GMT Subject: Tv via Internet 3000Canais 24horas Message-ID: <200909030450.n834oN4f001709@mx1.redhat.com> An HTML attachment was scrubbed... URL: From speedpro at bol.com.br Thu Sep 3 05:29:12 2009 From: speedpro at bol.com.br (Fabiane Menezes) Date: Thu, 3 Sep 2009 05:29:12 GMT Subject: Como ganhar na Loteria Message-ID: <200909030529.n835TG1I006357@mx1.redhat.com> An HTML attachment was scrubbed... URL: From apinto.po at gmail.com Thu Sep 3 17:21:47 2009 From: apinto.po at gmail.com (OFERTAS excepcionais) Date: Thu, 03 Sep 2009 20:21:47 +0300 Subject: =?utf-8?q?Experimente_sem_compromisso_e_ganhe_2_pr=C3=A9mios_exc?= =?utf-8?q?lusivos=0D=0A?= Message-ID: <20090903192154.B5B26623834E@mta2.serverpapaia.com> Se n?o conseguir visualizar este e-mail, clique aqui: www.serverpapaia.com/deco_proteste.html ----- Para deixar de receber as nossas novidades clique aqui http://www.serverpapaia.com/oem/unsubscribe.php?CampaignID=41&CampaignStatisticsID=53&Demo=0&EncryptedMemberID=MTU5NTk2NTgwMDA%3D&Email=dXRyYWNlLWRldmVsQHJlZGhhdC5jb20= -------------- next part -------------- An HTML attachment was scrubbed... URL: From mldireto at tudoemoferta.com.br Thu Sep 3 21:33:25 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Thu, 3 Sep 2009 18:33:25 -0300 Subject: Central de Alarme Auto-Instalavel Agility Message-ID: <28d3dc1e0875b7393099eec6001bf132@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From srikar at linux.vnet.ibm.com Fri Sep 4 07:38:47 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Fri, 04 Sep 2009 13:08:47 +0530 Subject: [PATCH 0/3] Fixes to gdbstub, uprobes. Message-ID: <20090904073847.13152.89411.sendpatchset@srdronam.in.ibm.com> Hi Frank, Utrace-devel The first two patches in this patchset fix report_signal callbacks in uprobes and gdbstub. >From Rolands message to utrace-devel, https://www.redhat.com/archives/utrace-devel/2009-August/msg00146.html we could rely on orig_ka == NULL to know if info->si_signo field for signal number indicates an actual signal or stale data. Roland, Oleg, can you please comment on the above check. This patchset changes report_signal callback of gdbstub engine so that it works similarly irrespective of the order in which they are connected. When two engines interested in the same event on a same task are attached, the order of report callbacks for that event depends on engine attach order. This is very important for gdbstub because uprobes report_signal can change the instruction pointer. The other patch fixes a bug introduced in recent defer registration patch. Subject: [PATCH 0/3] Fixes to gdbstub, uprobes. File: /tmp/gdbstub-patches/3/intro Subject: [PATCH 1/3] rework report_signal callback. File: /tmp/gdbstub-patches/3/redo_gdbstub_report_signal.patch Subject: [PATCH 2/3] Make singlestep in uprobes more robust. File: /tmp/gdbstub-patches/3/verify_and_then_post_process.patch Subject: [PATCH 3/3] Fix a bug in defer registration patch. File: /tmp/gdbstub-patches/3/fix_bug_defer_reg.patch -- Thanks and Regards Srikar Dronamraju From srikar at linux.vnet.ibm.com Fri Sep 4 07:38:58 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Fri, 04 Sep 2009 13:08:58 +0530 Subject: [PATCH 1/3] rework report_signal callback. In-Reply-To: <20090904073847.13152.89411.sendpatchset@srdronam.in.ibm.com> References: <20090904073847.13152.89411.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090904073858.13152.63654.sendpatchset@srdronam.in.ibm.com> Redo report_signal callback(). 1. Ensure we dont mistake signal_action just because another engine's report_signal callback has messed with UTRACE_SIGNAL_REPORT. i.e check orig_ka. 2. gdbstub works similarly irrespective of the order of the engines attached. If gdbstub attaches to a process thats already traced with uprobes then uprobes engine report_* callbacks tend to be called before gdbstub report_* callbacks. 3. This patch adds a additional field in gdb_connection current_gdb_uprobe that tracks the gdb_uprobe struct for the active uprobe. 4. This patch also adds find_gdb_uprobe() and find_gdb_connection helper functions. 5. No need to lock gdb_connections_mutex when unregistering uprobes. Signed-off-by: Srikar Dronamraju --- kernel/utrace-gdb.c | 334 +++++++++++++++++++++++++++++++-------------------- 1 files changed, 202 insertions(+), 132 deletions(-) diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index ac653fe..f8a07af 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -34,8 +34,10 @@ #include #include #include +#ifdef CONFIG_HAVE_UPROBES #include #include +#endif /** struct gdb_connection - Tracks one active gdb-process session. @@ -63,7 +65,18 @@ struct gdb_connection { int pass_signals; int stop_signals; /* XXX: per-thread later */ + +#ifdef CONFIG_HAVE_UPROBES + /* + * gdb_engine need not always be attached to the process before + * uprobes_engine. If uprobe's engine report_signal callback is + * called first, it would change the instruction address. Checking + * if the corresponding uprobe is disarmed can be easily be done by + * caching the gdb_uprobe pointer. + */ + struct gdb_uprobe *current_gdb_uprobe; /* XXX: per-thread later */ struct list_head uprobes; +#endif char output_buf[GDB_BUFMAX]; size_t output_buf_size; @@ -228,36 +241,78 @@ static void push_output_packet (struct gdb_connection *p, const char *s) push_output_packet_end(p, start); } +static inline struct gdb_connection *find_gdb_connection( + struct task_struct *task) +{ + struct gdb_connection *gc = NULL; + mutex_lock(&gdb_connections_mutex); + list_for_each_entry(gc, &gdb_connections, link) { + if (gc->target == task_tgid_nr(task)) + goto out_connection; + } + +out_connection: + mutex_unlock(&gdb_connections_mutex); + return gc; +} /* ------------------------------------------------------------------------ */ -static bool can_gdb_handle_sigtrap(struct pt_regs *regs, +#ifdef CONFIG_HAVE_UPROBES + +static inline struct gdb_uprobe *find_gdb_uprobe(unsigned long addr, struct gdb_connection *p) { - unsigned long bkpt = ubp_get_bkpt_addr (regs); - struct task_struct *task = current; + struct gdb_uprobe *gup, *gup2; - if (p->target == task_tgid_nr(task)) { - struct list_head *l; - struct list_head *l2; - struct gdb_uprobe *gup = NULL; + list_for_each_entry_safe(gup, gup2, &p->uprobes, link) { + pr_debug("considering addr=%p %s\n", (void *)gup->up.vaddr, + gup->disarmed_p ? "disarmed" : ""); + if (gup->up.vaddr == addr) + return gup; + } + return NULL; +} - list_for_each_safe(l, l2, &p->uprobes) { - gup = list_entry(l, struct gdb_uprobe, link); - pr_debug("considering addr=%p %s\n", - (void *)gup->up.vaddr, - gup->disarmed_p ? "disarmed" : ""); - if (gup->up.vaddr == bkpt && !gup->disarmed_p) - return true; - } +/* + * If no breakpoint, return false; + * If breakpoint and breakpoint is disarmed; return true + * If breakpoint and breakpoint is not disarmed; return false + */ +static inline bool is_bkpt_disarmed(struct pt_regs *regs, + struct gdb_connection *p) +{ + struct gdb_uprobe *gup = p->current_gdb_uprobe; + + if (!gup) { + unsigned long addr = ubp_get_bkpt_addr(regs); + + /* + * gup will be non-NULL iff uprobe engine report_signal + * callback was called before gdbstub engine's report_signal + * callback. i.e gdb_uprobe_handler was just called before + * calling this report_signal callback. + */ + gup = find_gdb_uprobe(addr, p); } + if (gup) + return gup->disarmed_p; + return false; } -#ifdef CONFIG_HAVE_UPROBES /* uprobe callback */ void gdb_uprobe_handler(struct uprobe *up, struct pt_regs *regs) { + struct gdb_connection *gc; + struct gdb_uprobe *gup; + + gc = find_gdb_connection(current); + if (!gc) + return; + + gup = container_of(up, struct gdb_uprobe, up); + gc->current_gdb_uprobe = gup; } void gdb_register_complete(struct uprobe *up, int regflag, int ret) @@ -292,12 +347,8 @@ void gdb_register_complete(struct uprobe *up, int regflag, int ret) } #endif /* CONFIG_HAVE_UPROBES */ - - - /* utrace callbacks */ - u32 gdb_utrace_report_quiesce(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *task, @@ -351,13 +402,15 @@ u32 gdb_utrace_report_exec(enum utrace_resume_action action, struct list_head *l; struct list_head *l2; list_for_each_safe(l, l2, & p->uprobes) { - struct gdb_uprobe *gup = list_entry (l, struct gdb_uprobe, link); - /* - int rc = unmap_uprobe (& gup->up); - WARN_ON (rc != 0); - */ - list_del (& gup->link); - kfree (gup); + struct gdb_uprobe *gup = list_entry(l, + struct gdb_uprobe, link); + unregister_uprobe(&gup->up); + /* + * int rc = unmap_uprobe(& gup->up); + * WARN_ON(rc != 0); + */ + list_del(&gup->link); + kfree(gup); } } #endif /* CONFIG_HAVE_UPROBES */ @@ -390,26 +443,28 @@ u32 gdb_utrace_report_signal(u32 action, pr_debug ("report_signal %d (0x%x) kern %d skip %d stop %d\n", task->pid, action, kern_p, p->pass_signals, p->stop_signals); - /* The target is about to receive a signal. There are several - * cases: - * - * 1) This is an ordinary signal. We UTRACE_STOP to notify gdb. - * - * 2a) This is a SIGTRAP arising from a uprobe. We UTRACE_RESUME, since - * we'll receive a uprobe_handler callback shortly, and can - * UTRACE_REPORT (with quiesce->stop) there. - * - * 2b) This is a SIGTRAP arising from a breakpoint, but not from a - * uprobe. We UTRACE_STOP to pass it to gdb. - * - * 3) This is a UTRACE_SIGNAL_REPORT our code injected to stop the process, - * as per UTRACE_INTERRUPT. We UTRACE_STOP | UTRACE_SIGNAL_IGN. - * - * 4) This is a signal our code injected on behalf of gdb via the C/S/I packets. - * We recognize this from p->pass_signals. We UTRACE_RESUME. - * - * 5) This is a UTRACE_SIGNAL_HANDLER event. UTRACE_RESUME. - */ + /* The target is about to receive a signal. There are several + * cases: + * + * 1) This is an ordinary signal. We UTRACE_STOP to notify gdb. + * + * 2a) This is a SIGTRAP arising from a singlestep arising from + * another tracing entity. Or a breakpoint is disarmed. + * We UTRACE_RESUME. + * + * 2b) This is a SIGTRAP but not from a singlestep. + * We UTRACE_STOP to pass it to gdb. + * + * 3) This is a UTRACE_SIGNAL_REPORT our code injected to stop the + * process, as per UTRACE_INTERRUPT. + * We UTRACE_STOP | UTRACE_SIGNAL_IGN. + * + * 4) This is a signal our code injected on behalf of gdb via the + * C/S/I packets. We recognize this from p->pass_signals. + * We UTRACE_RESUME. + * + * 5) This is a UTRACE_SIGNAL_HANDLER event. UTRACE_RESUME. + */ switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: /* case 5 */ @@ -417,44 +472,69 @@ u32 gdb_utrace_report_signal(u32 action, ret = UTRACE_RESUME | utrace_signal_action(action); break; - case UTRACE_SIGNAL_REPORT: /* case 3 */ - if (p->stop_signals > 0) { - p->stop_signals = 0; - snprintf (p->stopcode, GDB_BUFMAX, "S%02x", 2); /* SIGINT */ - push_output_packet (p, p->stopcode); - p->at_quiesce_do = UTRACE_STOP; - ret = UTRACE_STOP | UTRACE_SIGNAL_IGN; - } else { - ret = p->at_quiesce_do | utrace_signal_action(action); - } - break; + case UTRACE_SIGNAL_REPORT: + case UTRACE_SIGNAL_DELIVER: + case UTRACE_SIGNAL_IGN: /* XXX: bother notify? */ + case UTRACE_SIGNAL_TERM: + case UTRACE_SIGNAL_CORE: + case UTRACE_SIGNAL_STOP: + case UTRACE_SIGNAL_TSTP: + if (!orig_ka) { /* case 3a */ + /* This should be UTRACE_SIGNAL_REPORT */ + if (p->stop_signals > 0) { + p->stop_signals = 0; + /* Indicate as if thread received a SIGINT*/ + snprintf(p->stopcode, GDB_BUFMAX, "S%02x", 2); + push_output_packet(p, p->stopcode); + p->at_quiesce_do = UTRACE_STOP; + ret = UTRACE_STOP | UTRACE_SIGNAL_IGN; + } else + ret = p->at_quiesce_do | + utrace_signal_action(action); - case UTRACE_SIGNAL_DELIVER: - case UTRACE_SIGNAL_IGN: /* XXX: bother notify? */ - case UTRACE_SIGNAL_TERM: - case UTRACE_SIGNAL_CORE: - case UTRACE_SIGNAL_STOP: - case UTRACE_SIGNAL_TSTP: + break; + } + if (info->si_signo == SIGTRAP) { + if (test_thread_flag(TIF_SINGLESTEP) && + !p->stop_signals) + /* + * Case 2a: Thread is singlestepping, + * because some tracing utility other than + * gdbstub requested singlestep. Lets hand + * it over to them. + */ + ret = UTRACE_RESUME | + utrace_signal_action(action); #ifdef CONFIG_HAVE_UPROBES - if (info->si_signo == SIGTRAP) { /* case 2a */ - if (can_gdb_handle_sigtrap(regs, p)) { + else if (is_bkpt_disarmed(regs, p)) + /* + * Case 2a: Thread has hit a breakpoint but + * breakpoint is disarmed. + */ + ret = UTRACE_RESUME | + utrace_signal_action(action); +#endif /* CONFIG_HAVE_UPROBES */ + else { + /* + * Case 2b: Thread has hit a breakpoint or + * delivered a SIGTRAP signal. We need to + * know why? + */ p->at_quiesce_do = UTRACE_STOP; /* SIGTRAP */ snprintf(p->stopcode, GDB_BUFMAX, "S%02x", 5); push_output_packet(p, p->stopcode); ret = UTRACE_STOP | utrace_signal_action(action); - } else - ret = UTRACE_RESUME | - utrace_signal_action(action); + } + p->current_gdb_uprobe = NULL; break; } -#endif /* CONFIG_HAVE_UPROBES */ if (p->pass_signals > 0 /*&& kern_p*/) { /* case 4 */ p->pass_signals --; p->at_quiesce_do = UTRACE_RESUME; ret = UTRACE_RESUME | utrace_signal_action (action); /* deliver */ - } else { /* case 1, case 2b */ + } else { /* case 1 */ snprintf (p->stopcode, GDB_BUFMAX, "S%02x", map_signal_kern2gdb(info->si_signo)); push_output_packet (p, p->stopcode); @@ -494,13 +574,15 @@ u32 gdb_utrace_report_exit(enum utrace_resume_action action, struct list_head *l; struct list_head *l2; list_for_each_safe(l, l2, & p->uprobes) { - struct gdb_uprobe *gup = list_entry (l, struct gdb_uprobe, link); - /* - int rc = unmap_uprobe (& gup->up); - WARN_ON (rc != 0); - */ - list_del (& gup->link); - kfree (gup); + struct gdb_uprobe *gup = list_entry(l, + struct gdb_uprobe, link); + unregister_uprobe(&gup->up); + /* + * int rc = unmap_uprobe(& gup->up); + * WARN_ON(rc != 0); + */ + list_del(&gup->link); + kfree(gup); } } #endif /* CONFIG_HAVE_UPROBES */ @@ -533,13 +615,15 @@ u32 gdb_utrace_report_death(struct utrace_engine *engine, struct list_head *l; struct list_head *l2; list_for_each_safe(l, l2, & p->uprobes) { - struct gdb_uprobe *gup = list_entry (l, struct gdb_uprobe, link); - /* - int rc = unmap_uprobe (& gup->up); - WARN_ON (rc != 0); - */ - list_del (& gup->link); - kfree (gup); + struct gdb_uprobe *gup = list_entry(l, + struct gdb_uprobe, link); + unregister_uprobe(&gup->up); + /* + * int rc = unmap_uprobe(& gup->up); + * WARN_ON(rc != 0); + */ + list_del(&gup->link); + kfree(gup); } } #endif /* CONFIG_HAVE_UPROBES */ @@ -1071,26 +1155,18 @@ static void handle_gdb_command_packet (struct gdb_connection *p, struct task_str case 'Z': /* TYPE,ADDR,LENGTH */ rc = sscanf(& p->input_buf[2], "%lu,%lx,%lx", &arg1, &arg2, &arg3); pr_debug ("'Z' %lu %lx %lx\n", arg1, arg2, arg3); - if (rc != 3 || (arg1 > 1) /*|| (arg3 != 1)*/) { - push_output_packet(p, "E03"); - } else { - struct list_head *l; - struct list_head *l2; + if (rc != 3 || (arg1 > 1) /*|| (arg3 != 1)*/) + push_output_packet(p, "E03"); + else { struct gdb_uprobe *gup = NULL; - list_for_each_safe(l, l2, & p->uprobes) { - gup = list_entry (l, struct gdb_uprobe, link); - if (gup->up.vaddr == arg2) { - /* XXX: WARN_ON (gup->disarmed_p == 0) ? */ - gup->disarmed_p = 0; - push_output_packet (p, "OK"); - break; - } else { - gup = NULL; - } - } - - if (gup) /* breakpoint already exists */ + + gup = find_gdb_uprobe(arg2, p); + if (gup) { + /* XXX: WARN_ON (gup->disarmed_p == 1) ? */ + gup->disarmed_p = 0; + push_output_packet(p, "OK"); break; + } gup = kzalloc(sizeof(struct gdb_uprobe), GFP_KERNEL); if (!gup) { @@ -1117,29 +1193,24 @@ static void handle_gdb_command_packet (struct gdb_connection *p, struct task_str case 'z': /* TYPE,ADDR,LENGTH */ rc = sscanf(& p->input_buf[2], "%lu,%lx,%lx", &arg1, &arg2, &arg3); pr_debug ("'z' %lu %lx %lx\n", arg1, arg2, arg3); - if (rc != 3 || (arg1 > 1) /* || (arg3 != 1) */) { - push_output_packet(p, "E03"); - } else { - struct list_head *l; - struct list_head *l2; + if (rc != 3 || (arg1 > 1) /* || (arg3 != 1) */) + push_output_packet(p, "E03"); + else { struct gdb_uprobe *gup = NULL; - list_for_each_safe(l, l2, & p->uprobes) { - gup = list_entry (l, struct gdb_uprobe, link); - if (gup->up.vaddr == arg2) { - /* NB: We must not unregister_uprobe() here, - since most likely the thread/process is in UTRACE_STOP - state, with the single-step not even started. */ - /* XXX: WARN_ON (gup->disarmed_p == 1) ? */ - gup->disarmed_p = 1; - break; - } else { - gup = NULL; - } - } - if (gup == NULL) + + gup = find_gdb_uprobe(arg2, p); + if (gup) { + /* + * NB: We must not unregister_uprobe() here, + * since most likely the thread/process is + * in UTRACE_STOP state, with the + * single-step not even started. + */ + /* XXX: WARN_ON (gup->disarmed_p == 1) ? */ + gup->disarmed_p = 1; + push_output_packet(p, "OK"); + } else push_output_packet(p, "E04"); - else /* NB: not dereferencing gup. */ - push_output_packet(p, "OK"); } break; #endif /* CONFIG_HAVE_UPROBES */ @@ -1148,9 +1219,6 @@ static void handle_gdb_command_packet (struct gdb_connection *p, struct task_str } } - - - /* ------------------------------------------------------------------------ */ /* gdb control callbacks */ @@ -1207,12 +1275,14 @@ static int proc_gdb_open(struct inode *inode, struct file *filp) mutex_init(& p->input_mutex); init_waitqueue_head(& p->input_wait); - INIT_LIST_HEAD(&p->uprobes); - p->target = task->tgid; +#ifdef CONFIG_HAVE_UPROBES + INIT_LIST_HEAD(&p->uprobes); +#endif /* NB: During attach, we don't want to bother the target. Soon though a send_sig will interrupt it. */ p->at_quiesce_do = UTRACE_RESUME; + p->target = task->tgid; p->engine = utrace_attach_task(task, UTRACE_ATTACH_CREATE | @@ -1281,6 +1351,9 @@ static int proc_gdb_release(struct inode *inode, struct file *filp) ret = utrace_barrier(task, p->engine); } + list_del(&p->link); + mutex_unlock(&gdb_connections_mutex); + #ifdef CONFIG_HAVE_UPROBES { struct list_head *l, *l2; @@ -1295,11 +1368,8 @@ static int proc_gdb_release(struct inode *inode, struct file *filp) } #endif /* CONFIG_HAVE_UPROBES */ - list_del(&p->link); kfree(p); - mutex_unlock (& gdb_connections_mutex); - return ret; } From srikar at linux.vnet.ibm.com Fri Sep 4 07:39:08 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Fri, 04 Sep 2009 13:09:08 +0530 Subject: [PATCH 2/3] Make singlestep in uprobes more robust. In-Reply-To: <20090904073847.13152.89411.sendpatchset@srdronam.in.ibm.com> References: <20090904073847.13152.89411.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090904073908.13152.69695.sendpatchset@srdronam.in.ibm.com> Do singlestep post processing only when we are sure to have singlestepped. When there are multiple engines, we cannot rely on signal_action to be passed unchanged to report_signal callback of subsequent engines. Relying on signal_action and info->si_signo can lead to uprobes singlestepping when we shouldnt. (An interrupt after a breakpoint hit can very well look like a step signal.) This patch adds checks to ensure that user app has singlestepped before doing post processing. The checks are. 1. If orig_ka is NULL, then its mostly a UTRACE_SIGNAL_REPORT. 2. Verify from instruction_pointer if we have indeed singlestepped. Signed-off-by: Srikar Dronamraju --- kernel/uprobes_core.c | 65 ++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 54 insertions(+), 11 deletions(-) diff --git a/kernel/uprobes_core.c b/kernel/uprobes_core.c index 7cea30b..d784d4a 100644 --- a/kernel/uprobes_core.c +++ b/kernel/uprobes_core.c @@ -1456,6 +1456,38 @@ static void uprobe_inject_delayed_signals(struct list_head *delayed_signals) } /* + * Verify from Instruction Pointer if singlestep has indeed occurred. + * If Singlestep has occurred, then do post singlestep fix-ups. + */ +static bool validate_and_post_sstep(struct uprobe_task *utask, + struct pt_regs *regs, + struct uprobe_probept *ppt) +{ + unsigned long vaddr = instruction_pointer(regs); + + if (ppt->ubp.strategy & UBP_HNT_INLINE) { + /* + * If we have singlestepped, Instruction pointer cannot + * be same as virtual address of probepoint. + */ + if (vaddr == ppt->ubp.vaddr) + return false; + uprobe_post_ssin(utask, ppt, regs); +#ifdef CONFIG_UBP_XOL + } else { + /* + * If we have executed out of line, Instruction pointer + * cannot be same as virtual address of XOL slot. + */ + if (vaddr == ppt->ubp.xol_vaddr) + return false; + uprobe_post_ssout(utask, ppt, regs); +#endif + } + return true; +} + +/* * Helper routine for uprobe_report_signal(). * We get called here with: * state = UPTASK_RUNNING => we are here due to a breakpoint hit @@ -1487,7 +1519,8 @@ static void uprobe_inject_delayed_signals(struct list_head *delayed_signals) static u32 uprobe_handle_signal(u32 action, struct uprobe_task *utask, struct pt_regs *regs, - siginfo_t *info) + siginfo_t *info, + const struct k_sigaction *orig_ka) { struct uprobe_probept *ppt; struct uprobe_process *uproc; @@ -1507,7 +1540,13 @@ static u32 uprobe_handle_signal(u32 action, resume_action = UTRACE_SINGLESTEP; else resume_action = UTRACE_RESUME; - if (unlikely(signal_action == UTRACE_SIGNAL_REPORT)) { + /* + * This might be UTRACE_SIGNAL_REPORT request but some other + * engine's callback might have changed the signal action to + * something other than UTRACE_SIGNAL_REPORT. Use orig_ka to figure + * out such cases. + */ + if (unlikely(signal_action == UTRACE_SIGNAL_REPORT) || !orig_ka) { /* This thread was quiesced using UTRACE_INTERRUPT. */ bool done_quiescing; if (utask->active_probe) @@ -1625,17 +1664,20 @@ static u32 uprobe_handle_signal(u32 action, goto no_interest; down_read(&uproc->rwsem); - /* No further need to re-assert UTRACE_SINGLESTEP. */ - clear_utrace_quiesce(utask, false); ppt = utask->active_probe; BUG_ON(!ppt); -#ifdef CONFIG_UBP_XOL - if (!(ppt->ubp.strategy & UBP_HNT_INLINE)) - uprobe_post_ssout(utask, ppt, regs); - else -#endif - uprobe_post_ssin(utask, ppt, regs); + /* + * Havent singlestepped yet? then re-assert + * UTRACE_SINGLESTEP. + */ + if (!validate_and_post_sstep(utask, regs, ppt)) { + up_read(&uproc->rwsem); + goto no_interest; + } + + /* No further need to re-assert UTRACE_SINGLESTEP. */ + clear_utrace_quiesce(utask, false); bkpt_done: /* Note: Can come here after running uretprobe handlers */ @@ -1703,7 +1745,8 @@ static u32 uprobe_report_signal(u32 action, /* Keep uproc intact until just before we return. */ uprobe_get_process(uproc); - report_action = uprobe_handle_signal(action, utask, regs, info); + report_action = uprobe_handle_signal(action, utask, regs, info, + orig_ka); doomed = utask->doomed; if (uprobe_put_process(uproc, true)) From srikar at linux.vnet.ibm.com Fri Sep 4 07:39:18 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Fri, 04 Sep 2009 13:09:18 +0530 Subject: [PATCH 3/3] Fix a bug in defer registration patch. In-Reply-To: <20090904073847.13152.89411.sendpatchset@srdronam.in.ibm.com> References: <20090904073847.13152.89411.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090904073918.13152.72545.sendpatchset@srdronam.in.ibm.com> This patch fixes the leak in uproc refcount when a tracing thread does defer_registration. When threads queue defer_registration, uprobes was leaking uproc refcount. If a tracing process requested a [un]register operation that was defered, then subsequent removal of all probes would still keep the uprobes engine active till the thread dies. Jim Keniston's observation on uprobes lifetime made me figure out an error in defer_registration patch that I sent earlier. Signed-off-by: Srikar Dronamraju --- kernel/uprobes_core.c | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-) diff --git a/kernel/uprobes_core.c b/kernel/uprobes_core.c index d784d4a..27c2977 100644 --- a/kernel/uprobes_core.c +++ b/kernel/uprobes_core.c @@ -945,10 +945,8 @@ int register_uprobe(struct uprobe *u) */ BUG_ON(utask->state != UPTASK_SSTEP); if (task_is_stopped_or_traced(utask->tsk)) { - put_pid(p); ret = defer_registration(u, 1, utask); - up_write(&uproc->rwsem); - return ret; + goto fail_uproc; } } } else { @@ -1127,10 +1125,8 @@ void unregister_uprobe(struct uprobe *u) /* See comment in register_uprobe(). */ BUG_ON(utask->state != UPTASK_SSTEP); if (task_is_stopped_or_traced(utask->tsk)) { - put_pid(p); (void) defer_registration(u, 0, utask); - up_write(&uproc->rwsem); - return; + goto done; } } uk = (struct uprobe_kimg *)u->kdata; From roland at redhat.com Fri Sep 4 09:39:27 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Sep 2009 02:39:27 -0700 (PDT) Subject: [PATCH] utrace_stop: fix UTRACE_DETACH race In-Reply-To: Oleg Nesterov's message of Tuesday, 1 September 2009 20:21:53 +0200 <20090901182153.GA15431@redhat.com> References: <20090820194251.GA29913@redhat.com> <20090824235821.328A7414DF@magilla.sf.frob.com> <20090826102759.GA5455@redhat.com> <20090831024657.0A01B45B02@magilla.sf.frob.com> <20090831134837.GA11861@redhat.com> <20090831193828.35A9845B02@magilla.sf.frob.com> <20090901182153.GA15431@redhat.com> Message-ID: <20090904093927.B01738B12A@magilla.sf.frob.com> Sorry for the delay. I merged those 3 patches. Thanks, Roland From roland at redhat.com Fri Sep 4 09:45:06 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Sep 2009 02:45:06 -0700 (PDT) Subject: [PATCH 16-19] mv ptrace options into engine->data In-Reply-To: Oleg Nesterov's message of Wednesday, 2 September 2009 23:24:24 +0200 <20090902212424.GA4286@redhat.com> References: <20090902212424.GA4286@redhat.com> Message-ID: <20090904094506.18B728B12A@magilla.sf.frob.com> I merged these. My review nits you can follow up on at your leisure. Thanks, Roland From roland at redhat.com Fri Sep 4 09:49:30 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Sep 2009 02:49:30 -0700 (PDT) Subject: [PATCH 17] introduce ptrace_context->options In-Reply-To: Oleg Nesterov's message of Wednesday, 2 September 2009 23:24:32 +0200 <20090902212432.GA4300@redhat.com> References: <20090902212432.GA4300@redhat.com> Message-ID: <20090904094930.87CBE8B12A@magilla.sf.frob.com> > Add "int options" into struct ptrace_context. Will be used to hold > PT_XXX options. Currently is not used, but: IMHO the traditional PT_* bit assignments are useless. We should just store and use the PTRACE_O_* bits directly. > - introduce __ptrace_set_options() helper which updates ->options > and utrace events mask. Despite overly-common kernel practice, __foo is a lousy name for anything. The only place where I think __foo makes sense for new code is when foo is a wrapper that takes a lock around calling __foo. I'd prefer if we can just pick meaningful names for new internal functions. __ names are especially pointless for static functions. > +static inline > +struct ptrace_context *ptrace_context(struct utrace_engine *engine) > +{ > + return engine->data; > +} When the prototype doesn't fit on a line, the usual way to break it is: static inline struct ptrace_context * ptrace_context(struct utrace_engine *engine) But anyway, what's the point of this helper? What's wrong with or any less clear about plain: struct ptrace_context *ctx = engine->data; ? Thanks, Roland From roland at redhat.com Fri Sep 4 09:50:13 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Sep 2009 02:50:13 -0700 (PDT) Subject: [PATCH 19] "disable" tracehook_prepare_clone() In-Reply-To: Oleg Nesterov's message of Wednesday, 2 September 2009 23:24:38 +0200 <20090902212438.GA4310@redhat.com> References: <20090902212438.GA4310@redhat.com> Message-ID: <20090904095013.361D98B131@magilla.sf.frob.com> > I need to re-check this, but iirc this hook is not needed at all since > "[PATCH 10] ptrace_report_clone: rework auto-attaching". It certainly should never be needed in the clean version of reality. Thanks, Roland From roland at redhat.com Fri Sep 4 09:55:29 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Sep 2009 02:55:29 -0700 (PDT) Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: Oleg Nesterov's message of Wednesday, 2 September 2009 23:23:49 +0200 <20090902212349.GA3953@redhat.com> References: <20090814144555.GA28295@redhat.com> <20090818045433.511254730F@magilla.sf.frob.com> <20090818181732.GA17634@redhat.com> <20090818211627.6F0274730F@magilla.sf.frob.com> <20090819135323.GC632@redhat.com> <20090824064736.2F3D7414DF@magilla.sf.frob.com> <20090902212349.GA3953@redhat.com> Message-ID: <20090904095529.5FFCA8B12A@magilla.sf.frob.com> > Simple answer. Because I do not know how to implement this. At least now. > I tried to think of this more, but I don't see how to make the first steps. > > (Yes, to be honest, this looks like "unnecessary complication" to me, I have > to admit. But this is not the reason.) Well, I am befuddled. I explained the model and it seems obvious to me how you'd go about it, the only nontrivial corner being coping with the MT exec reap case. But I won't let our mutual befuddlement stand in the way of making immediate progress the way you like best. > Agreed, but nobody else cares ;) Ananth, Srikar, Jim, Frank? (Beuller?) We do have some people around here with some experience dealing with the API. They made me add the engine ref counts in the first place, for Pete's sake. They've got to have some opinions! > So, I am going to use the simple ops->release method for now. Once we > have the working code we can reconsider the lifetime rules for engine/ > engine->data. Agreed. Thanks, Roland From srikar at linux.vnet.ibm.com Fri Sep 4 11:55:10 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Fri, 4 Sep 2009 17:25:10 +0530 Subject: Should SIGNAL_REPORT take preference to queued signal? Message-ID: <20090904115510.GA2900@linux.vnet.ibm.com> Hi Roland, Oleg I hit upon a case where a traced thread steps over a inserted breakpoint instruction, and the tracing engine requests the traced thread to be interrupted. Here the traced thread calls report_signal callback with UTRACE_REPORT_SIGNAL and later does a report_signal callback with UTRACE_SIGNAL_CORE. We do have a comment in utrace_get_signal() which does indicate the behaviour I see. /* * We've been asked for an explicit report before we * even check for pending signals. */ However I was looking if there were reasons why "interrupt" from a tracing thread would be preferred over a "queued signal"? I am seeing this situation in Uprobes. A uprobes enabled tracer wanted to remove a breakpoint and hence requested the thread to stop using utrace_control with action being UTRACE_STOP. Since utrace_control returns -EINPROGRESS, and thread state _not_ being in TASK_INTERRUPTIBLE state, the tracer requests for utrace_control with action this time being UTRACE_INTERRUPT. Right at this time, the tracing thread steps over the trap. This causes uprobe_report_signal() to be called with signal_action == UTRACE_SIGNAL_REPORT instead of (say) UTRACE_SIGNAL_CORE. Now tracer is able to remove the breakpoint. However on resuming the thread sees that it has a signal pending and delivers the signal, this time lets say action is UTRACE_SIGNAL_CORE. Since uprobes doesnt see a breakpoint there, it resumes. However resuming after stepping a breakpoint but without fix-ups could lead to disastrous results. Currently we do have a way in uprobes to handle this situation. i.e to check if any threads have stepped on breakpoint instruction related to the breakpoint that we are removing and if there are any such threads then fixup their Instruction Pointers. -- Thanks and Regards Srikar From ananth at in.ibm.com Fri Sep 4 13:02:37 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Fri, 4 Sep 2009 18:32:37 +0530 Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: <20090904095529.5FFCA8B12A@magilla.sf.frob.com> References: <20090814144555.GA28295@redhat.com> <20090818045433.511254730F@magilla.sf.frob.com> <20090818181732.GA17634@redhat.com> <20090818211627.6F0274730F@magilla.sf.frob.com> <20090819135323.GC632@redhat.com> <20090824064736.2F3D7414DF@magilla.sf.frob.com> <20090902212349.GA3953@redhat.com> <20090904095529.5FFCA8B12A@magilla.sf.frob.com> Message-ID: <20090904130237.GE12691@in.ibm.com> On Fri, Sep 04, 2009 at 02:55:29AM -0700, Roland McGrath wrote: > > Simple answer. Because I do not know how to implement this. At least now. > > I tried to think of this more, but I don't see how to make the first steps. > > > > (Yes, to be honest, this looks like "unnecessary complication" to me, I have > > to admit. But this is not the reason.) > > Well, I am befuddled. I explained the model and it seems obvious to me how > you'd go about it, the only nontrivial corner being coping with the MT exec > reap case. But I won't let our mutual befuddlement stand in the way of > making immediate progress the way you like best. > > > Agreed, but nobody else cares ;) > > Ananth, Srikar, Jim, Frank? (Beuller?) We do have some people around > here with some experience dealing with the API. They made me add the > engine ref counts in the first place, for Pete's sake. They've got to > have some opinions! I am not sure if all of what I say here makes any sense as I am still in the midst of understanding the discussion threads between the two of you (admittedly, its one hairy piece of the kernel). However, here goes: I prefer Roland's ops->release approach. However, is there any chance that ->ops is no longer valid at the time __utrace_release_engine() is called? For the ptrace case at least, it'll always be valid, so there are no issues. The concept of how utrace engines use refcnts initially befuddled me. The entity that does a utrace_attach_*, without it having to explicitly ask for a utrace_engine_get(), already owns a reference. That was counter intuitive. (That's the reason for a series of Srikar's utrace_engine_put() fixes too, I guess). That apart, the problem of freeing ->data is similar to what Prasad is trying to grapple in hardware watchpoints and its ptrace interaction. I guess its a problem unique to ptrace(?). The issue there, is that when ptrace did a register_user_hardware_watchpoint(), and that thread later died/exec'd, ptrace may (will?) not actually unregister the watchpoint, and the hwbkpt layer is left to fend for itself in cleaning up the struct hw_breakpoint in flush_thread_hardware_watchpoint(). Now, you could have non-ptrace users of the interface (who may have passed just a reference to a statically allocated struct hw_breakpoint) in which case, freeing the structure in the hwbkpt layer is just wrong. Right now, the way Prasad has fixed it is to have a check if the bp->triggered == ptrace_triggered, in which case, free up the structure. Yes, there is a kind of layering violation here -- hwbkpt now knows about ptrace_triggered. But I am not sure if there is a better way of fixing it. Ananth From oleg at redhat.com Fri Sep 4 13:24:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Sep 2009 15:24:53 +0200 Subject: [RFC, PATCH] teach utrace to destroy engine->data In-Reply-To: <20090904130237.GE12691@in.ibm.com> References: <20090814144555.GA28295@redhat.com> <20090818045433.511254730F@magilla.sf.frob.com> <20090818181732.GA17634@redhat.com> <20090818211627.6F0274730F@magilla.sf.frob.com> <20090819135323.GC632@redhat.com> <20090824064736.2F3D7414DF@magilla.sf.frob.com> <20090902212349.GA3953@redhat.com> <20090904095529.5FFCA8B12A@magilla.sf.frob.com> <20090904130237.GE12691@in.ibm.com> Message-ID: <20090904132453.GA8353@redhat.com> On 09/04, Ananth N Mavinakayanahalli wrote: > > I prefer Roland's ops->release approach. Yes! me too. > However, is there any chance > that ->ops is no longer valid Sure, ->ops can be changed at "any time". For example, just because of UTRACE_DETACH. That is why utrace_attach_task() saves ->release pointer in engine. But this is transparent for the user, and engine->release is private. We can change the implementation so that ->ops is never changed. > The concept of how utrace engines use refcnts initially befuddled me. > The entity that does a utrace_attach_*, without it having to explicitly > ask for a utrace_engine_get(), already owns a reference. That was > counter intuitive. Otherwise, how can we use the returned engine? The task can be killed right after utrace_attach_ and disappear. In this case release_task() path must do utrace_engine_put(). This looks very natural to me. Oleg. From mike.gordon at primus.ca Fri Sep 4 14:37:00 2009 From: mike.gordon at primus.ca (mike gordon) Date: Fri, 04 Sep 2009 10:37:00 -0400 Subject: Informatica Customer Lists Message-ID: <4eef6791263f514f8f5efbe1c57cc091@user-108dae7915> We are pleased to announce the availability of the following customer lists: Informatica Documentum Remedy Patrol MQ Software Microsoft Sharepoint Lotus Connections Primavera Microsoft Project ATG Websphere Commerce Netsuite Click Commerce Sterling Commerce Biztalk FRX CRM System Center Visual Studio VAR If you would like more information or a sample off any of our lists, please contact us at (905) 721-8456 or email us at repharm1 at aol.com, Also we have the following lists as well Below are just some of the lists available: ERP (ENTERPRISE RESOURCE PLANNING): Baan JD Edwards Lawson Made2Manage Mapics Marcam Oracle Peoplesoft SAP SSA E-BUSINESS APPLICATIONS: Ariba BMC BroadVision Commerce One Webtrends MIDDLEWARE/CONNECTIVITY/APP SERVERS/WEB SERVERS: Bea Systems Iona Unisys OPERATING SYSTEMS/HARDWARE/SOFTWARE: COMPAQ HP 3000 HP 9000 HP-UX IBM AS/400 IBM OS/390 Lotus Notes Microsoft Sun Microsystems DATABASE: DB2 FileMaker Informix Oracle SQL SybaseCRM (CUSTOMER RELATIONSHIP MANAGEMENT): Clarify E.piphany HNC Onyx Pivotal Siebel Vantive Xchange SUPPLY CHAIN: Agile i2 Technologies Manugistics QAD Webplan COMMUNICATIONS: Nortel Cisco 3com Siemens Alcatel Telecom Vars ASP's CLECS ISP's E-COMMERCE: Dot Com Directory Consultant Directory Software Directory EXECUTIVE DIRECTORIES: Chief Executive Officer Chief Financial Officer Chief Information Officer Engineering Human Resources Purchasing Sales/Marketing INDUSTRY SPECIFIC LISTS: Agriculture, Forestry and Fishing, Communications, Construction, Finance, Insurance and Real Estate, Manufacturing, Mining, Public Administration, Retail Trade, Services, Transportation, Utilities, Wholesale -------------- next part -------------- An HTML attachment was scrubbed... URL: From groyne at toontown.co.uk Fri Sep 4 15:07:04 2009 From: groyne at toontown.co.uk (Tenny) Date: Fri, 04 Sep 2009 23:07:04 +0800 Subject: man was the Message-ID: <4AA12C11.9050404@toontown.co.uk> Ngs, eighteen inches across and an inch thick. They took their time to cook, for the f -------------- next part -------------- A non-text attachment was scrubbed... Name: inquiring.jpg Type: image/jpeg Size: 9928 bytes Desc: not available URL: From oleg at redhat.com Fri Sep 4 15:04:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Sep 2009 17:04:41 +0200 Subject: [PATCH 17] introduce ptrace_context->options In-Reply-To: <20090904094930.87CBE8B12A@magilla.sf.frob.com> References: <20090902212432.GA4300@redhat.com> <20090904094930.87CBE8B12A@magilla.sf.frob.com> Message-ID: <20090904150441.GA13633@redhat.com> On 09/04, Roland McGrath wrote: > > > Add "int options" into struct ptrace_context. Will be used to hold > > PT_XXX options. Currently is not used, but: > > IMHO the traditional PT_* bit assignments are useless. > We should just store and use the PTRACE_O_* bits directly. Ah. Why, why I have not thought of it? > > - introduce __ptrace_set_options() helper which updates ->options > > and utrace events mask. > > Despite overly-common kernel practice, __foo is a lousy name for anything. > The only place where I think __foo makes sense for new code is when foo is > a wrapper that takes a lock around calling __foo. I'd prefer if we can > just pick meaningful names for new internal functions. __ names are > especially pointless for static functions. Agreed... ptrace_set_events? I agree with any naming. > > +static inline > > +struct ptrace_context *ptrace_context(struct utrace_engine *engine) > > +{ > > + return engine->data; > > +} > > When the prototype doesn't fit on a line, the usual way to break it is: > > static inline struct ptrace_context * > ptrace_context(struct utrace_engine *engine) OK. > But anyway, what's the point of this helper? > What's wrong with or any less clear about plain: > > struct ptrace_context *ctx = engine->data; > > ? Nothing wrong. I added this trivial helper just in case, if we change the lifetime rules for engine->data. I will keep it for now, but we can kill it at any moment. Oleg. From oleg at redhat.com Fri Sep 4 18:39:06 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Sep 2009 20:39:06 +0200 Subject: [PATCH 20-23] mv ptrace options into engine->data Message-ID: <20090904183906.GA29810@redhat.com> Finish this change... Now we should change ptrace_set_action()/etc to use ptrace_context, and start some functional changes. But I encountered the problem, see patch 23. Oleg. From oleg at redhat.com Fri Sep 4 18:39:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Sep 2009 20:39:09 +0200 Subject: [PATCH 20] ptrace_set_options: use PTRACE_O_ instead of PT_ Message-ID: <20090904183909.GA29818@redhat.com> Roland McGrath wrote: > > IMHO the traditional PT_* bit assignments are useless. > We should just store and use the PTRACE_O_* bits directly. Agreed! --- kernel/ptrace.c | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) --- PU/kernel/ptrace.c~20_DONt_USE_PT_XXX 2009-09-04 17:08:49.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-04 18:01:09.000000000 +0200 @@ -28,8 +28,8 @@ struct ptrace_context { int options; }; -static inline -struct ptrace_context *ptrace_context(struct utrace_engine *engine) +static inline struct ptrace_context * +ptrace_context(struct utrace_engine *engine) { return engine->data; } @@ -507,7 +507,7 @@ static inline int __ptrace_set_options(s UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; context->options = options; - if (options & PT_TRACE_EXIT) + if (options & PTRACE_O_TRACEEXIT) events |= UTRACE_EVENT(EXIT); return utrace_set_events(target, engine, events); @@ -905,33 +905,11 @@ static int ptrace_setoptions(struct task static int ptrace_set_options(struct task_struct *child, long data) { struct utrace_engine *engine; - int options = 0; - - if (data & PTRACE_O_TRACESYSGOOD) - options |= PT_TRACESYSGOOD; - - if (data & PTRACE_O_TRACEFORK) - options |= PT_TRACE_FORK; - - if (data & PTRACE_O_TRACEVFORK) - options |= PT_TRACE_VFORK; - - if (data & PTRACE_O_TRACECLONE) - options |= PT_TRACE_CLONE; - - if (data & PTRACE_O_TRACEEXEC) - options |= PT_TRACE_EXEC; - - if (data & PTRACE_O_TRACEVFORKDONE) - options |= PT_TRACE_VFORK_DONE; - - if (data & PTRACE_O_TRACEEXIT) - options |= PT_TRACE_EXIT; engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, &ptrace_utrace_ops, NULL); if (likely(!IS_ERR(engine))) { - __ptrace_set_options(child, engine, options); + __ptrace_set_options(child, engine, data & PTRACE_O_MASK); utrace_engine_put(engine); } From oleg at redhat.com Fri Sep 4 18:39:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Sep 2009 20:39:12 +0200 Subject: [PATCH 21] use context->options instead of "->ptrace & PT_" Message-ID: <20090904183912.GA29821@redhat.com> Convert ptrace.c to use context->options. I guess ptrace_report_clone() still needs changes... bbut hopefully ptrace_clone_attach() is fine. --- --- PU/kernel/ptrace.c~21_USE_CTX_OPTS 2009-09-04 18:01:09.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-04 18:33:03.000000000 +0200 @@ -204,7 +204,9 @@ static u32 ptrace_report_exec(enum utrac const struct linux_binprm *bprm, struct pt_regs *regs) { - if (task->ptrace & PT_TRACE_EXEC) + struct ptrace_context *context = ptrace_context(engine); + + if (context->options & PTRACE_O_TRACEEXEC) return utrace_ptrace_event(task, PTRACE_EVENT_EXEC, 0); /* @@ -264,7 +266,7 @@ static u32 ptrace_report_clone(enum utra int event; if ((clone_flags & CLONE_VFORK) && - (parent->ptrace & PT_TRACE_VFORK_DONE)) { + (context->options & PTRACE_O_TRACEVFORKDONE)) { /* * Stash the child PID for a PTRACE_EVENT_VFORK_DONE report, * even if we don't report this clone event itself. Mark @@ -284,12 +286,12 @@ static u32 ptrace_report_clone(enum utra event = 0; if (clone_flags & CLONE_VFORK) { - if (parent->ptrace & PT_TRACE_VFORK) + if (context->options & PTRACE_O_TRACEVFORK) event = PTRACE_EVENT_VFORK; } else if ((clone_flags & CSIGNAL) != SIGCHLD) { - if (parent->ptrace & PT_TRACE_CLONE) + if (context->options & PTRACE_O_TRACECLONE) event = PTRACE_EVENT_CLONE; - } else if (parent->ptrace & PT_TRACE_FORK) { + } else if (context->options & PTRACE_O_TRACEFORK) { event = PTRACE_EVENT_FORK; } @@ -306,10 +308,12 @@ static u32 ptrace_report_clone(enum utra return UTRACE_RESUME; } -static u32 ptrace_report_syscall(u32 action, struct task_struct *task) +static u32 ptrace_report_syscall(u32 action, struct utrace_engine *engine, + struct task_struct *task) { + struct ptrace_context *context = ptrace_context(engine); int code = SIGTRAP; - if (task->ptrace & PT_TRACESYSGOOD) + if (context->options & PTRACE_O_TRACESYSGOOD) code |= 0x80; return utrace_ptrace_report(action, task, PTRACE_EVENT_SYSCALL, code); } @@ -326,7 +330,7 @@ static u32 ptrace_report_syscall_entry(u if (ptrace_syscall_action(task)) return UTRACE_SYSCALL_ABORT | UTRACE_RESUME; - return ptrace_report_syscall(UTRACE_SYSCALL_RUN, task); + return ptrace_report_syscall(UTRACE_SYSCALL_RUN, engine, task); } /* @@ -364,7 +368,7 @@ static u32 ptrace_report_syscall_exit(en */ user_disable_single_step(task); - return ptrace_report_syscall(0, task); + return ptrace_report_syscall(0, engine, task); } static u32 ptrace_resumed(struct task_struct *task, @@ -970,6 +974,7 @@ static int ptrace_setsiginfo(struct task static int ptrace_resume(struct task_struct *child, long request, long data) { struct utrace_engine *engine; + struct ptrace_context *context; enum utrace_resume_action action; enum utrace_syscall_action syscall; int ret = 0; @@ -982,6 +987,8 @@ static int ptrace_resume(struct task_str if (IS_ERR(engine)) return -ESRCH; + context = ptrace_context(engine); + syscall = UTRACE_SYSCALL_RUN; #ifdef PTRACE_SYSEMU if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) @@ -1040,7 +1047,7 @@ static int ptrace_resume(struct task_str */ if (request == PTRACE_SYSCALL) { data = SIGTRAP; - if (child->ptrace & PT_TRACESYSGOOD) + if (context->options & PTRACE_O_TRACESYSGOOD) data |= 0x80; ptrace_set_stop_event(child, PTRACE_EVENT_SYSCALL); @@ -1076,7 +1083,7 @@ static int ptrace_resume(struct task_str */ data = 0; event = 0; - if (child->ptrace & PT_TRACE_VFORK_DONE) { + if (context->options & PTRACE_O_TRACEVFORKDONE) { ptrace_set_stop_event(child, PTRACE_EVENT_VFORK); action = UTRACE_REPORT; From oleg at redhat.com Fri Sep 4 18:39:14 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Sep 2009 20:39:14 +0200 Subject: [PATCH 22] kill ptrace_setoptions() and ptrace_update_utrace() Message-ID: <20090904183914.GA29828@redhat.com> Now that we don't use "ptrace & PT_" we can kill ptrace_setoptions() and ptrace_update_utrace(). We could also remove all PT_ defines except PT_PTRACED and PT_PTRACE_CAP. --- kernel/ptrace.c | 73 -------------------------------------------------------- 1 file changed, 73 deletions(-) --- PU/kernel/ptrace.c~22_KILL_PT_XXX 2009-09-04 18:33:03.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-04 19:50:35.000000000 +0200 @@ -85,46 +85,6 @@ void __ptrace_unlink(struct task_struct arch_ptrace_untrace(child); } -static int ptrace_update_utrace(struct task_struct *task, - struct utrace_engine *engine) -{ - unsigned long events; - - /* - * We need this for resume handling. - */ - events = UTRACE_EVENT(QUIESCE); - - /* - * These events are always reported. - */ - events |= UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; - - /* - * We always have to examine clone events to check for CLONE_PTRACE. - */ - events |= UTRACE_EVENT(CLONE); - - /* - * PTRACE_SETOPTIONS can request more events. - */ - if (task->ptrace & PT_TRACE_EXIT) - events |= UTRACE_EVENT(EXIT); - - if (!engine) { - int ret; - engine = utrace_attach_task(task, UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); - if (IS_ERR(engine)) - return -ESRCH; - ret = utrace_set_events(task, engine, events); - utrace_engine_put(engine); - return ret; - } - - return utrace_set_events(task, engine, events); -} - static void ptrace_set_action(struct task_struct *task, enum utrace_resume_action action, enum utrace_syscall_action syscall) @@ -253,7 +213,6 @@ static void ptrace_clone_attach(struct t sigaddset(&child->pending.signal, SIGSTOP); set_tsk_thread_flag(child, TIF_SIGPENDING); - ptrace_update_utrace(child, NULL); } static u32 ptrace_report_clone(enum utrace_resume_action action, @@ -875,37 +834,6 @@ int ptrace_writedata(struct task_struct return copied; } -/* will die soon ... */ -static int ptrace_setoptions(struct task_struct *child, long data) -{ - child->ptrace &= ~PT_TRACE_MASK; - - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - - if (data & PTRACE_O_TRACEFORK) - child->ptrace |= PT_TRACE_FORK; - - if (data & PTRACE_O_TRACEVFORK) - child->ptrace |= PT_TRACE_VFORK; - - if (data & PTRACE_O_TRACECLONE) - child->ptrace |= PT_TRACE_CLONE; - - if (data & PTRACE_O_TRACEEXEC) - child->ptrace |= PT_TRACE_EXEC; - - if (data & PTRACE_O_TRACEVFORKDONE) - child->ptrace |= PT_TRACE_VFORK_DONE; - - if (data & PTRACE_O_TRACEEXIT) - child->ptrace |= PT_TRACE_EXIT; - - ptrace_update_utrace(child, NULL); - - return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; -} - static int ptrace_set_options(struct task_struct *child, long data) { struct utrace_engine *engine; @@ -1160,7 +1088,6 @@ int ptrace_request(struct task_struct *c case PTRACE_OLDSETOPTIONS: #endif case PTRACE_SETOPTIONS: - ret = ptrace_setoptions(child, data); ret = ptrace_set_options(child, data); break; case PTRACE_GETEVENTMSG: From oleg at redhat.com Fri Sep 4 18:39:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Sep 2009 20:39:17 +0200 Subject: [PATCH 23] ptrace_attach_task: kill WARN_ON(err) (perhars we can improve ->reporting logic?) Message-ID: <20090904183917.GA29832@redhat.com> ptrace_attach_task: engine = utrace_attach_task(CREATE | EXCLUSIVE); err = utrace_set_events(); WARN_ON(err && !tracee->exit_state); Looks correct but it is not. utrace_attach_task() can return EINPROGRESS. Note that start_callback/etc sets ->reporting = engine even if we are not going to call ->report_any(). I'll try to think, perhaps we can change this code to check engine->flags first... Note that EINPROGRESS can happen even if there are no other tracers. utrace_add_engine() sets ->report and the tracee can call utrace_resume() before we do utrace_set_events(). I think that it makes sense to check utrace_flags & QUIESCE in utrace_resume() and return if it is not set. But even with this change EINPROGRESS is still possible if we have other engines. But the real problem is, _sometimes_ "make xcheck" triggers this warning, and I can not understand: 1. Why I didn't see it before context->options was added 2. I changed utrace_resume() to check QUIESCE. But I still see the warning! Still investigating... --- kernel/ptrace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) --- PU/kernel/ptrace.c~23_ATTACH_KILL_WARNING 2009-09-04 19:50:35.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-04 19:57:47.000000000 +0200 @@ -505,8 +505,7 @@ static int ptrace_attach_task(struct tas * It can fail only if the tracee is dead, the caller * must notice this before setting PT_PTRACED. */ - err = __ptrace_set_options(tracee, engine, options); - WARN_ON(err && !tracee->exit_state); + __ptrace_set_options(tracee, engine, options); utrace_engine_put(engine); return 0; } From oleg at redhat.com Fri Sep 4 18:58:59 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Sep 2009 20:58:59 +0200 Subject: [PATCH] utrace_resume: check QUIESCE before list_for_each_entry() Message-ID: <20090904185859.GA31590@redhat.com> Not sure this makes real sense, but perhaps it would be tidier to check QUIESCE in utrace_resume. I wonder if we still have reasons to set ->report + TIF_NOTIFY_RESUME in utrace_add_engine(). Looks like this is not needed now, but I am not sure. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) --- __UTRACE/kernel/utrace.c~3_RESUME_CK_QUIESCE 2009-09-01 20:07:45.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-04 20:48:18.000000000 +0200 @@ -1831,11 +1831,13 @@ void utrace_resume(struct task_struct *t return; } + start_report(utrace); + + if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) + return; /* * Do a simple reporting pass, with no callback after report_quiesce. */ - start_report(utrace); - list_for_each_entry(engine, &utrace->attached, entry) start_callback(utrace, &report, engine, task, 0); From roland at redhat.com Fri Sep 4 20:06:31 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Sep 2009 13:06:31 -0700 (PDT) Subject: Should SIGNAL_REPORT take preference to queued signal? In-Reply-To: Srikar Dronamraju's message of Friday, 4 September 2009 17:25:10 +0530 <20090904115510.GA2900@linux.vnet.ibm.com> References: <20090904115510.GA2900@linux.vnet.ibm.com> Message-ID: <20090904200631.62ECA2F@magilla.sf.frob.com> > However I was looking if there were reasons why "interrupt" from a > tracing thread would be preferred over a "queued signal"? This is the fundamental point of requesting utrace reports (either UTRACE_REPORT or UTRACE_INTERRUPT)--the tracer gets control before any user-visible action can happen. Dequeuing a signal is a user-visible action. The problem you are having is that the signal you're concerned with is not a "real" signal. It's one that you have instigated. This is a well-known issue. In fact, it's one of the motivating issues for utrace, but it's always been a "fix this later on" plan. You can see the same issue with ptrace today. For example, if a debugger is using single-step and then exits suddenly, there can be a pending SIGTRAP left from the single-step, that then gets delivered to the process after the debugger is no longer there to intercept it. The eternal to-do list item for this is "utrace extension events". In short, to stop overloading signals for these debugger purposes and use a dedicated utrace notification mechanism instead. I've long had a few ideas about the details of this, but it all remains to be fleshed out. I don't think we want to try to get into that until after the basic utrace code gets merged upstream. Thanks, Roland From roland at redhat.com Fri Sep 4 20:11:35 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Sep 2009 13:11:35 -0700 (PDT) Subject: [PATCH 17] introduce ptrace_context->options In-Reply-To: Oleg Nesterov's message of Friday, 4 September 2009 17:04:41 +0200 <20090904150441.GA13633@redhat.com> References: <20090902212432.GA4300@redhat.com> <20090904094930.87CBE8B12A@magilla.sf.frob.com> <20090904150441.GA13633@redhat.com> Message-ID: <20090904201135.7FBEA2F@magilla.sf.frob.com> > Ah. Why, why I have not thought of it? Your mind is filled with the actual hard parts, that's why! :-) I'm only dabbling enough to make the obvious suggestions. > Agreed... ptrace_set_events? I agree with any naming. Sure. I'm not really picky either, I just hate the stupid __ names. Anything that makes a little intrinsic sense is fine. > Nothing wrong. I added this trivial helper just in case, if we change > the lifetime rules for engine->data. I will keep it for now, but we > can kill it at any moment. Ok. I suspect that if there is anything else it will require more code in the caller anyway (such as a return value check or a paired unlock call). But it doesn't hurt. Thanks, Roland From roland at redhat.com Sat Sep 5 01:45:38 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Sep 2009 18:45:38 -0700 (PDT) Subject: [PATCH] utrace_resume: check QUIESCE before list_for_each_entry() In-Reply-To: Oleg Nesterov's message of Friday, 4 September 2009 20:58:59 +0200 <20090904185859.GA31590@redhat.com> References: <20090904185859.GA31590@redhat.com> Message-ID: <20090905014538.7DEF28BEB6@magilla.sf.frob.com> > Not sure this makes real sense, but perhaps it would be tidier to > check QUIESCE in utrace_resume. I think the theory was that getting there without it set would be very unlikely. That wasn't really true with the report-on-attach behavior. But it should be without that (read on). OTOH, the bit test is very cheap in comparison to even one pointless iteration of that loop, so no harm in a short-circuit check. However, I am not sure it is safe to jump around finish_resume_report(). I have been failing to come up with the exact scenario. But I'm concerned that missing user_disable_single_step() there could matter in some situation where UTRACE_SINGLESTEP was used before. > I wonder if we still have reasons to set ->report + TIF_NOTIFY_RESUME > in utrace_add_engine(). Looks like this is not needed now, but I am > not sure. There was never a reason to force a report soon after attach. What mattered is that start_report() sees ->report set and knows to take the lock and do splice_attaching() before the next reporting pass. There are no guarantees about actual races with a reporting pass that is starting asynchronously. But the attacher can know by external means that the attach finished before a traced event happened, e.g. it saw the tracee blocked in a syscall right after utrace_attach_task() returned, or an hour has passed since the attach. Please review commit 04852f3. I added a separate flag to guarantee start_report() notices pending attaches without using TIF_NOTIFY_RESUME. Thanks, Roland From roland at redhat.com Sat Sep 5 01:53:12 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Sep 2009 18:53:12 -0700 (PDT) Subject: [PATCH 23] ptrace_attach_task: kill WARN_ON(err) (perhars we can improve ->reporting logic?) In-Reply-To: Oleg Nesterov's message of Friday, 4 September 2009 20:39:17 +0200 <20090904183917.GA29832@redhat.com> References: <20090904183917.GA29832@redhat.com> Message-ID: <20090905015312.CF87B8BEB6@magilla.sf.frob.com> > ptrace_attach_task: > > engine = utrace_attach_task(CREATE | EXCLUSIVE); > > err = utrace_set_events(); > WARN_ON(err && !tracee->exit_state); > > Looks correct but it is not. utrace_attach_task() can return EINPROGRESS. utrace_set_events() can, yes. I think the old code just predates utrace_barrier() et al. That can just be: if (err && err != -EINPROGRESS) WARN_ON(!tracee->exit_state); to keep the sanity check. > Note that start_callback/etc sets ->reporting = engine even if we are not > going to call ->report_any(). I'll try to think, perhaps we can change this > code to check engine->flags first... I think the barrier logic in start_callback() won't allow that. > Note that EINPROGRESS can happen even if there are no other tracers. That's fine. It just means "not synchronized yet". I suppose we could make utrace_set_events() skip it when it's not clearing any bits. > But the real problem is, _sometimes_ "make xcheck" triggers this warning, > and I can not understand: > > 1. Why I didn't see it before context->options was added > > 2. I changed utrace_resume() to check QUIESCE. But I still > see the warning! > > Still investigating... I don't have any answers to those off hand. Thanks, Roland From renzo at cs.unibo.it Sat Sep 5 10:55:40 2009 From: renzo at cs.unibo.it (Renzo Davoli) Date: Sat, 5 Sep 2009 12:55:40 +0200 Subject: Bug: report_reap is never called Message-ID: <20090905105522.GB427@cs.unibo.it> Hi Ronald & utrace developers.... I am back... I am upgrading my kmview support and I have stepped into a clear bug. in utrace_reap: ---------- list_for_each_entry_safe(engine, next, &utrace->attached, entry) { ops = engine->ops; engine->ops = NULL; engine->flags = 0; list_move(&engine->entry, &detached); /* * If it didn't need a callback, we don't need to drop * the lock. Now nothing else refers to this engine. */ if (!(engine->flags & UTRACE_EVENT(REAP))) continue; ------------ The code following this 'if' is never executed (i.e. the reap callback never called). In fact it is impossible for (engine->flags & UTRACE_EVENT(REAP)) to be true given that a few statement above engine->flags has been set to 0! To fix the bug: clean all the events but reap: engine->flags &= UTRACE_EVENT(REAP); or save the flag in a temporary var before cleaning it, as you do for engine->ops. ciao renzo From polatel at gmail.com Sat Sep 5 15:01:58 2009 From: polatel at gmail.com (Ali Polatel) Date: Sat, 5 Sep 2009 18:01:58 +0300 Subject: Questions about utrace Message-ID: <20090905150158.GG7071@harikalardiyari> Hey everyone, I've been writing a ptrace based sandboxing tool, called sydbox?, and I want to explain about some of my bad experiences with ptrace and whether utrace will fix these deficiencies. First of all ptrace() makes it rather hard writing portable code that will work for every architecture. You have to find out registry numbers for every architecture. It would be really nice if there were a common interface like utrace_get_syscall(), utrace_set_syscall() that works for every architecture supported. Basically sydbox intercepts some system calls and checks their arguments. Using ptrace, however, it's not possible to stop the children only at the entry of system calls we are interested in but we have to stop them at _every_ system call and check for the system call number. Because of this threaded applications run very slowly under sydbox as we have to stop them at every sched_yield(). I know that utrace will split PTRACE_SYSCALL into two calls SYSCALL_ENTRY and SYSCALL_EXIT and this is really cool but maybe the ability to stop the children only at system calls the caller is interested in is a better idea. Last but not least, I want to thank you for your efforts to create a nicer tracing API for Linux. Peace! ?: http://github.com/alip/sydbox -- Regards, Ali Polatel -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From oleg at redhat.com Sun Sep 6 13:44:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 6 Sep 2009 15:44:53 +0200 Subject: [PATCH 1/4] utrace_reap: fix engine->flags usage Message-ID: <20090906134453.GA24697@redhat.com> Renzo Davoli wrote: > > The code following this 'if' is never executed (i.e. the reap callback never > called). > In fact it is impossible for (engine->flags & UTRACE_EVENT(REAP)) to be > true given that a few statement above engine->flags has been set to 0! Good catch! there was a recent cleanup with the small side effect ;) Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) --- __UTRACE/kernel/utrace.c~1_FIX_FLAGS 2009-09-06 13:35:18.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-06 15:06:27.000000000 +0200 @@ -410,12 +410,14 @@ static void utrace_reap(struct task_stru { struct utrace_engine *engine, *next; const struct utrace_engine_ops *ops; + unsigned long flags; LIST_HEAD(detached); restart: splice_attaching(utrace); list_for_each_entry_safe(engine, next, &utrace->attached, entry) { ops = engine->ops; + flags = engine->flags; engine->ops = NULL; engine->flags = 0; list_move(&engine->entry, &detached); @@ -424,7 +426,7 @@ restart: * If it didn't need a callback, we don't need to drop * the lock. Now nothing else refers to this engine. */ - if (!(engine->flags & UTRACE_EVENT(REAP))) + if (!(flags & UTRACE_EVENT(REAP))) continue; /* From oleg at redhat.com Sun Sep 6 13:44:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 6 Sep 2009 15:44:56 +0200 Subject: [PATCH 2/4] utrace_reap: do not play with ->reporting Message-ID: <20090906134456.GA24701@redhat.com> utrace_reap(), like other reporting loops, sets/clears utrace->reporting, but this is not needed. We already set ->ops = NULL, this means utrace_barrier() will never look at reporting. get_utrace_lock() can not succeed, it must return -ESRCH and utrace_barrier() just returns in this case. But more importantly, I think utrace_reap() never needs to synchronize with utrace_barrier(). Once we drop utrace->lock, any other caller which takes this lock must see both ->exit_state and utrace->reap. This means utrace_control() or utrace_set_events() which sets/clears REAP must not succeed. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 9 --------- 1 file changed, 9 deletions(-) --- __UTRACE/kernel/utrace.c~2_NO_REPORTING 2009-09-06 15:06:27.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-06 15:09:59.000000000 +0200 @@ -429,19 +429,10 @@ restart: if (!(flags & UTRACE_EVENT(REAP))) continue; - /* - * This synchronizes with utrace_barrier(). Since we - * need the utrace->lock here anyway (unlike the other - * reporting loops), we don't need any memory barrier - * as utrace_barrier() holds the lock. - */ - utrace->reporting = engine; spin_unlock(&utrace->lock); (*ops->report_reap)(engine, target); - utrace->reporting = NULL; - put_detached_list(&detached); spin_lock(&utrace->lock); From oleg at redhat.com Sun Sep 6 13:44:59 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 6 Sep 2009 15:44:59 +0200 Subject: [PATCH 3/4] utrace_reap: Message-ID: <20090906134459.GA24708@redhat.com> >From the previous changelog: > > Once we drop utrace->lock, any other caller which takes this lock must > see both ->exit_state and utrace->reap. This means utrace_control() or > utrace_set_events() which sets/clears REAP must not succeed. IOW, nobody change change engine->ops or REAP bit in flags. Nobody can add the new engine or remove it from ->attached. We can do all work lockless and without barriers. To simplify the review, utrace_reap() becomes: static void utrace_reap(struct task_struct *target, struct utrace *utrace) __releases(utrace->lock) { struct utrace_engine *engine; splice_attaching(utrace); spin_unlock(&utrace->lock); /* * We were called with utrace->reap set: * nobody can set/clear UTRACE_EVENT(REAP) in engine->flags or * change engine->ops, and nobody can change utrace->attached. */ list_for_each_entry(engine, &utrace->attached, entry) { if (engine->flags & UTRACE_EVENT(REAP)) engine->ops->report_reap(engine, target); engine->ops = NULL; engine->flags = 0; } put_detached_list(&utrace->attached); } Note that I changed the logic a bit, we set ->ops = NULL after ->report_reap(). Is it OK? If not, it is trivial to change. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) --- __UTRACE/kernel/utrace.c~3_NO_LOCKING 2009-09-06 15:09:59.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-06 15:06:23.000000000 +0200 @@ -408,40 +408,25 @@ static void put_detached_list(struct lis static void utrace_reap(struct task_struct *target, struct utrace *utrace) __releases(utrace->lock) { - struct utrace_engine *engine, *next; - const struct utrace_engine_ops *ops; - unsigned long flags; - LIST_HEAD(detached); + struct utrace_engine *engine; -restart: splice_attaching(utrace); - list_for_each_entry_safe(engine, next, &utrace->attached, entry) { - ops = engine->ops; - flags = engine->flags; + spin_unlock(&utrace->lock); + /* + * We were called with utrace->reap set: + * nobody can set/clear UTRACE_EVENT(REAP) in engine->flags or + * change engine->ops, and nobody can change utrace->attached. + */ + list_for_each_entry(engine, &utrace->attached, entry) { + if (engine->flags & UTRACE_EVENT(REAP)) + engine->ops->report_reap(engine, target); + engine->ops = NULL; engine->flags = 0; - list_move(&engine->entry, &detached); - /* - * If it didn't need a callback, we don't need to drop - * the lock. Now nothing else refers to this engine. - */ - if (!(flags & UTRACE_EVENT(REAP))) - continue; - - spin_unlock(&utrace->lock); - - (*ops->report_reap)(engine, target); - - put_detached_list(&detached); - - spin_lock(&utrace->lock); - goto restart; } - spin_unlock(&utrace->lock); - - put_detached_list(&detached); + put_detached_list(&utrace->attached); } /* From oleg at redhat.com Sun Sep 6 13:45:02 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 6 Sep 2009 15:45:02 +0200 Subject: [PATCH 4/4] utrace_release_task: check REAP before utrace_reap() Message-ID: <20090906134502.GA24711@redhat.com> Again, I am not sure this make sense as a cleanup, up to you. But utrace_release_task() can check UTRACE_EVENT(REAP) and optimize out utrace_reap() when there are no attached engines. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) --- __UTRACE/kernel/utrace.c~4_CK_REAP 2009-09-06 15:06:23.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-06 15:37:33.000000000 +0200 @@ -442,7 +442,9 @@ void utrace_release_task(struct task_str utrace->reap = 1; - if (!(target->utrace_flags & _UTRACE_DEATH_EVENTS)) { + if ((target->utrace_flags & + (UTRACE_EVENT(REAP) & _UTRACE_DEATH_EVENTS)) == + UTRACE_EVENT(REAP)) { utrace_reap(target, utrace); /* Unlocks and frees. */ return; } From oleg at redhat.com Sun Sep 6 13:50:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 6 Sep 2009 15:50:53 +0200 Subject: [PATCH 3/4] utrace_reap: do not play with lock/unlock/restart In-Reply-To: <20090906134459.GA24708@redhat.com> References: <20090906134459.GA24708@redhat.com> Message-ID: <20090906135053.GA24960@redhat.com> (fix the subject) >From the previous changelog: > > Once we drop utrace->lock, any other caller which takes this lock must > see both ->exit_state and utrace->reap. This means utrace_control() or > utrace_set_events() which sets/clears REAP must not succeed. IOW, nobody change change engine->ops or REAP bit in flags. Nobody can add the new engine or remove it from ->attached. We can do all work lockless and without barriers. To simplify the review, utrace_reap() becomes: static void utrace_reap(struct task_struct *target, struct utrace *utrace) __releases(utrace->lock) { struct utrace_engine *engine; splice_attaching(utrace); spin_unlock(&utrace->lock); /* * We were called with utrace->reap set: * nobody can set/clear UTRACE_EVENT(REAP) in engine->flags or * change engine->ops, and nobody can change utrace->attached. */ list_for_each_entry(engine, &utrace->attached, entry) { if (engine->flags & UTRACE_EVENT(REAP)) engine->ops->report_reap(engine, target); engine->ops = NULL; engine->flags = 0; } put_detached_list(&utrace->attached); } Note that I changed the logic a bit, we set ->ops = NULL after ->report_reap(). Is it OK? If not, it is trivial to change. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) --- __UTRACE/kernel/utrace.c~3_NO_LOCKING 2009-09-06 15:09:59.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-06 15:06:23.000000000 +0200 @@ -408,40 +408,25 @@ static void put_detached_list(struct lis static void utrace_reap(struct task_struct *target, struct utrace *utrace) __releases(utrace->lock) { - struct utrace_engine *engine, *next; - const struct utrace_engine_ops *ops; - unsigned long flags; - LIST_HEAD(detached); + struct utrace_engine *engine; -restart: splice_attaching(utrace); - list_for_each_entry_safe(engine, next, &utrace->attached, entry) { - ops = engine->ops; - flags = engine->flags; + spin_unlock(&utrace->lock); + /* + * We were called with utrace->reap set: + * nobody can set/clear UTRACE_EVENT(REAP) in engine->flags or + * change engine->ops, and nobody can change utrace->attached. + */ + list_for_each_entry(engine, &utrace->attached, entry) { + if (engine->flags & UTRACE_EVENT(REAP)) + engine->ops->report_reap(engine, target); + engine->ops = NULL; engine->flags = 0; - list_move(&engine->entry, &detached); - /* - * If it didn't need a callback, we don't need to drop - * the lock. Now nothing else refers to this engine. - */ - if (!(flags & UTRACE_EVENT(REAP))) - continue; - - spin_unlock(&utrace->lock); - - (*ops->report_reap)(engine, target); - - put_detached_list(&detached); - - spin_lock(&utrace->lock); - goto restart; } - spin_unlock(&utrace->lock); - - put_detached_list(&detached); + put_detached_list(&utrace->attached); } /* From oleg at redhat.com Sun Sep 6 16:22:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 6 Sep 2009 18:22:22 +0200 Subject: [PATCH] utrace_resume: check QUIESCE before list_for_each_entry() In-Reply-To: <20090905014538.7DEF28BEB6@magilla.sf.frob.com> References: <20090904185859.GA31590@redhat.com> <20090905014538.7DEF28BEB6@magilla.sf.frob.com> Message-ID: <20090906162222.GA1678@redhat.com> On 09/04, Roland McGrath wrote: > > Please review commit 04852f3. I added a separate flag to guarantee > start_report() notices pending attaches without using TIF_NOTIFY_RESUME. Yes, the new flag looks nice! But please see 2 patches I'll send in a minute. Just one question, this patch also changes utrace_report_death: @@ -1714,6 +1705,7 @@ void utrace_report_death utrace->death = 1; utrace->report = 0; utrace->interrupt = 0; + splice_attaching(utrace); But, afaics, we need this fix with or without ->slow_path ? Oleg. From oleg at redhat.com Sun Sep 6 16:26:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 6 Sep 2009 18:26:31 +0200 Subject: [PATCH 1/2] utrace_add_engine() should set ->utrace_flags |= REAP Message-ID: <20090906162631.GA2048@redhat.com> Before 04852f35ff95f2a48cf8c38faf365b7d61f4370a we had invariant: ->utrace_flags != 0 if and only if we have attached engines, now we don't because utrace_add_engine() does not set REAP. I believe this invariant is very nice, and it is better to keep it. Note also that if utrace_add_engine() does not set REAP, then we should also change utrace_reset() which preserves this bit. I think this change is dangerous. For example, I sent "[PATCH 4/4] utrace_release_task: check REAP before utrace_reap()" https://www.redhat.com/archives/utrace-devel/2009-September/msg00049.html before I reviewed this commit. Again, I am not sure this patch is really needed, but it looks like an obviously correct optimization. Now it is not. Or, suppose we decide to optimize tracehook_force_sigpending(). It does 2 checks why only one is needed, it could be just static inline int tracehook_force_sigpending(void) { return utrace_interrupt_pending(); } Now we can't do this, because engine = utrace_attach_task(task); utrace_control(task, engine, UTRACE_INTERRUPT); causes lockup. Another example. utrace_control() does the sanity check before it proceeds. No! now it is not a sanity check, it is needed for correctness. Otherwise engine = utrace_attach_task(task); utrace_control(task, engine, UTRACE_REPORT); Now, do_notify_resume() calls tracehook_notify_resume() which does nothing because task_utrace_flags() == 0 and clears TIF_NOTIFY_RESUME. But we didn't clear utrace->report! This means we can never set TIF_NOTIFY_RESUME again, we check !->report first. Heh, and given that utrace_control checks "action >= UTRACE_REPORT", this commit is slightly wrong. Because utrace_control(INTERRUPT) after attach sets ->interrupt + TIF_SIGPENDING, utrace_get_signal() won't be called, recalc_sigpending() clears TIF_SIGPENDING and we have the dangling ->interrupt set. Please revert this change ;) Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 4 ++++ 1 file changed, 4 insertions(+) --- __UTRACE/kernel/utrace.c~5_ADD_MUST_SET_REAP 2009-09-06 16:44:07.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-06 18:07:14.000000000 +0200 @@ -164,7 +164,11 @@ static int utrace_add_engine(struct task * callback, that would mean the new engine also gets * notified about the event that precipitated its own * creation. This is not what the user wants. + * + * In case we had no engines before, make sure that + * utrace_flags is not zero. */ + target->utrace_flags |= UTRACE_EVENT(REAP); list_add_tail(&engine->entry, &utrace->attaching); utrace->slow_path = 1; ret = 0; From oleg at redhat.com Sun Sep 6 16:26:34 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 6 Sep 2009 18:26:34 +0200 Subject: [PATCH 2/2] utrace->report does not need utrace->slow_path Message-ID: <20090906162634.GA2052@redhat.com> Every time we set ->report, we also set ->slow_path. This complication is not necessary. Instead we can change start_report() to check both flags. This is free, gcc is good enough. This code void test_func(struct utrace *utrace) { if (utrace->slow_path || utrace->report) do_something(); } is compiled to test_func: pushq %rbp testb $-126, 96(%rdi), movq %rsp, %rbp, jne .L449, leave ret .L449: call do_something leave ret Perhaps it makes sense to rename ->slow_path, with it only means that splice_attaching() is needed and nothing more. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) --- __UTRACE/kernel/utrace.c~6_DONT_ABUSE_SLOW_WORK 2009-09-06 18:07:14.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-06 18:15:39.000000000 +0200 @@ -644,7 +644,7 @@ static bool utrace_do_stop(struct task_s } spin_unlock_irq(&target->sighand->siglock); } else if (!utrace->report && !utrace->interrupt) { - utrace->report = utrace->slow_path = 1; + utrace->report = 1; set_notify_resume(target); } @@ -773,7 +773,7 @@ relock: /* * Ensure a reporting pass when we're resumed. */ - utrace->report = utrace->slow_path = 1; + utrace->report = 1; set_thread_flag(TIF_NOTIFY_RESUME); } @@ -1096,7 +1096,7 @@ int utrace_control(struct task_struct *t */ clear_engine_wants_stop(engine); if (!utrace->report && !utrace->interrupt) { - utrace->report = utrace->slow_path = 1; + utrace->report = 1; set_notify_resume(target); } break; @@ -1266,14 +1266,13 @@ struct utrace_report { /* * We are now making the report, so clear the flag saying we need one. - * When ->report is set, ->slow_path is always set too. When there is a - * new attach, ->slow_path is set even without ->report, just so we will - * know to do splice_attaching() here before the callback loop. + * When there is a new attach, ->slow_path is set without ->report, just + * so we will know to do splice_attaching() here before the callback loop. */ static void start_report(struct utrace *utrace) { BUG_ON(utrace->stopped); - if (utrace->slow_path) { + if (utrace->report || utrace->slow_path) { spin_lock(&utrace->lock); splice_attaching(utrace); utrace->report = 0; @@ -1310,7 +1309,7 @@ static void finish_report(struct utrace_ utrace->interrupt = 1; set_tsk_thread_flag(task, TIF_SIGPENDING); } else { - utrace->report = utrace->slow_path = 1; + utrace->report = 1; set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); } spin_unlock(&utrace->lock); From ananth at in.ibm.com Mon Sep 7 06:26:08 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Mon, 7 Sep 2009 11:56:08 +0530 Subject: Questions about utrace In-Reply-To: <20090905150158.GG7071@harikalardiyari> References: <20090905150158.GG7071@harikalardiyari> Message-ID: <20090907062608.GB3994@in.ibm.com> On Sat, Sep 05, 2009 at 06:01:58PM +0300, Ali Polatel wrote: > Hey everyone, > I've been writing a ptrace based sandboxing tool, called sydbox?, and I > want to explain about some of my bad experiences with ptrace and whether > utrace will fix these deficiencies. > > First of all ptrace() makes it rather hard writing portable code that > will work for every architecture. You have to find out registry numbers > for every architecture. It would be really nice if there were a common > interface like utrace_get_syscall(), utrace_set_syscall() that > works for every architecture supported. Have you looked at using syscall_get_(nr/error/arguments/return_value) et al in arch//include/asm/syscall.h > Basically sydbox intercepts some system calls and checks their > arguments. Using ptrace, however, it's not possible to stop the children > only at the entry of system calls we are interested in but we have to > stop them at _every_ system call and check for the system call number. > Because of this threaded applications run very slowly under sydbox as we > have to stop them at every sched_yield(). I know that utrace will split > PTRACE_SYSCALL into two calls SYSCALL_ENTRY and SYSCALL_EXIT and this is > really cool but maybe the ability to stop the children only at system > calls the caller is interested in is a better idea. Utrace engine callbacks happen in the traced task context and as such, are extremely fast. For the case you have, it isn't difficult for your ops->report_syscall_entry to either do a UTRACE_STOP/UTRACE_RESUME depending on what syscall_get_nr() returned. Aside, have you looked at seccomp? The utrace/seccomp branch on the utrace git tree has some work Roland had done earlier to make seccomp use utrace. Ananth From polatel at gmail.com Mon Sep 7 13:24:08 2009 From: polatel at gmail.com (Ali Polatel) Date: Mon, 7 Sep 2009 16:24:08 +0300 Subject: Questions about utrace In-Reply-To: <20090907062608.GB3994@in.ibm.com> References: <20090905150158.GG7071@harikalardiyari> <20090907062608.GB3994@in.ibm.com> Message-ID: <20090907131926.GB1513@harikalardiyari.ev> Ananth N Mavinakayanahalli yazm??: > On Sat, Sep 05, 2009 at 06:01:58PM +0300, Ali Polatel wrote: > > Hey everyone, > > I've been writing a ptrace based sandboxing tool, called sydbox?, and I > > want to explain about some of my bad experiences with ptrace and whether > > utrace will fix these deficiencies. > > > > First of all ptrace() makes it rather hard writing portable code that > > will work for every architecture. You have to find out registry numbers > > for every architecture. It would be really nice if there were a common > > interface like utrace_get_syscall(), utrace_set_syscall() that > > works for every architecture supported. > > Have you looked at using syscall_get_(nr/error/arguments/return_value) > et al in arch//include/asm/syscall.h This is exactly what I wanted! > > Basically sydbox intercepts some system calls and checks their > > arguments. Using ptrace, however, it's not possible to stop the children > > only at the entry of system calls we are interested in but we have to > > stop them at _every_ system call and check for the system call number. > > Because of this threaded applications run very slowly under sydbox as we > > have to stop them at every sched_yield(). I know that utrace will split > > PTRACE_SYSCALL into two calls SYSCALL_ENTRY and SYSCALL_EXIT and this is > > really cool but maybe the ability to stop the children only at system > > calls the caller is interested in is a better idea. > > Utrace engine callbacks happen in the traced task context and as such, > are extremely fast. For the case you have, it isn't difficult for your > ops->report_syscall_entry to either do a UTRACE_STOP/UTRACE_RESUME > depending on what syscall_get_nr() returned. Sounds cool. > Aside, have you looked at seccomp? The utrace/seccomp branch on the > utrace git tree has some work Roland had done earlier to make seccomp > use utrace. I've just checked it out and the interface looks a lot cleaner. I'm really impressed, thanks for the hard work! Are there any assumptions when utrace will be merged? > Ananth > -- Regards, Ali Polatel -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From fche at redhat.com Mon Sep 7 16:21:22 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Mon, 07 Sep 2009 12:21:22 -0400 Subject: Questions about utrace In-Reply-To: <20090905150158.GG7071@harikalardiyari> (Ali Polatel's message of "Sat, 5 Sep 2009 18:01:58 +0300") References: <20090905150158.GG7071@harikalardiyari> Message-ID: Ali Polatel writes: > [...] Basically sydbox intercepts some system calls and checks > their arguments. Using ptrace, however, it's not possible to stop > the children only at the entry of system calls we are interested in > but we have to stop them at _every_ system call and check for the > system call number. [...] This is because, at the point where the relevant utrace hooks exists, it does not matter what system call is being run. There is only one hook, and it takes all syscalls off of the normal path, so by nature someone must demultiplex after the fact. The utrace way is to make that someone be the utrace-engine client. If you want to instrument system calls individually, you may need to use another technology. (In systemtap we support per-syscall but system-wide kprobes, and per-thread but syscall-wide utrace probes.) Per-process per-syscall tracepoint widgetry is under construction but I don't think it's widely available yet, but that could be your target. All of this involves kernel-side (module) programming, by the way. - FChE From roland at redhat.com Mon Sep 7 19:17:12 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 7 Sep 2009 12:17:12 -0700 (PDT) Subject: Bug: report_reap is never called In-Reply-To: Renzo Davoli's message of Saturday, 5 September 2009 12:55:40 +0200 <20090905105522.GB427@cs.unibo.it> References: <20090905105522.GB427@cs.unibo.it> Message-ID: <20090907191712.C8E3D8BECC@magilla.sf.frob.com> Oops! I broke that in d4bcb571, a change I no longer remember the reason for. I'm sure it was for a subtler bug Oleg noticed, should be a thread in this archive about it. Should be fixed now in commit 2e12892. Thanks, Roland From roland at redhat.com Mon Sep 7 19:21:30 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 7 Sep 2009 12:21:30 -0700 (PDT) Subject: [PATCH] utrace_resume: check QUIESCE before list_for_each_entry() In-Reply-To: Oleg Nesterov's message of Sunday, 6 September 2009 18:22:22 +0200 <20090906162222.GA1678@redhat.com> References: <20090904185859.GA31590@redhat.com> <20090905014538.7DEF28BEB6@magilla.sf.frob.com> <20090906162222.GA1678@redhat.com> Message-ID: <20090907192130.81AA48BECC@magilla.sf.frob.com> > Just one question, this patch also changes utrace_report_death: > > @@ -1714,6 +1705,7 @@ void utrace_report_death > utrace->death = 1; > utrace->report = 0; > utrace->interrupt = 0; > + splice_attaching(utrace); > > But, afaics, we need this fix with or without ->slow_path ? Yes, I just noticed it along the way. I should have mentioned it in the log. Thanks, Roland From roland at redhat.com Mon Sep 7 19:23:42 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 7 Sep 2009 12:23:42 -0700 (PDT) Subject: [PATCH 1/2] utrace_add_engine() should set ->utrace_flags |= REAP In-Reply-To: Oleg Nesterov's message of Sunday, 6 September 2009 18:26:31 +0200 <20090906162631.GA2048@redhat.com> References: <20090906162631.GA2048@redhat.com> Message-ID: <20090907192342.2161A8BECC@magilla.sf.frob.com> > Before 04852f35ff95f2a48cf8c38faf365b7d61f4370a we had invariant: > ->utrace_flags != 0 if and only if we have attached engines, now > we don't because utrace_add_engine() does not set REAP. I think that was an accidental deletion. I can't see any reason I would have done it. > I believe this invariant is very nice, and it is better to keep it. I agree completely. Thanks, Roland From roland at redhat.com Mon Sep 7 19:34:47 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 7 Sep 2009 12:34:47 -0700 (PDT) Subject: [PATCH 2/2] utrace->report does not need utrace->slow_path In-Reply-To: Oleg Nesterov's message of Sunday, 6 September 2009 18:26:34 +0200 <20090906162634.GA2052@redhat.com> References: <20090906162634.GA2052@redhat.com> Message-ID: <20090907193447.2EBC98BECC@magilla.sf.frob.com> > Every time we set ->report, we also set ->slow_path. This complication is > not necessary. Instead we can change start_report() to check both flags. > This is free, gcc is good enough. It was originally just ->pending_attach, but then I look at start_report() and overmicrooptimized before I even committed it. I've put it back that way now. Thanks, Roland From roland at redhat.com Mon Sep 7 20:17:41 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 7 Sep 2009 13:17:41 -0700 (PDT) Subject: [PATCH 4/4] utrace_release_task: check REAP before utrace_reap() In-Reply-To: Oleg Nesterov's message of Sunday, 6 September 2009 15:45:02 +0200 <20090906134502.GA24711@redhat.com> References: <20090906134502.GA24711@redhat.com> Message-ID: <20090907201741.3A2DE8BEBC@magilla.sf.frob.com> > Again, I am not sure this make sense as a cleanup, up to you. > But utrace_release_task() can check UTRACE_EVENT(REAP) and > optimize out utrace_reap() when there are no attached engines. In the original code, utrace_release_task() would not be called at all when there are no engines attached. IMHO that is the optimization we want to get back to. It may still be too early in the morning for me to be thinking clearly. But what about this? Thanks, Roland diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index e249770..0000000 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h @@ -362,7 +362,12 @@ static inline void tracehook_report_vfor */ static inline void tracehook_prepare_release_task(struct task_struct *task) { - utrace_release_task(task); + /* + * See kernel/utrace.c:utrace_attach_task() about this barrier. + */ + smp_mb(); + if (task_utrace_flags(task)) + utrace_release_task(task); } /** diff --git a/kernel/utrace.c b/kernel/utrace.c index 76d0d84..0000000 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -143,13 +143,13 @@ static int utrace_add_engine(struct task spin_lock(&utrace->lock); - if (utrace->reap) { + if (unlikely(utrace->reap)) { /* * Already entered utrace_release_task(), cannot attach now. */ ret = -ESRCH; } else if ((flags & UTRACE_ATTACH_EXCLUSIVE) && - unlikely(matching_engine(utrace, flags, ops, data))) { + unlikely(matching_engine(utrace, flags, ops, data))) { ret = -EEXIST; } else { /* @@ -216,16 +216,19 @@ struct utrace_engine *utrace_attach_task utrace = &target->utrace; - if (unlikely(target->exit_state == EXIT_DEAD)) { - /* - * The target has already been reaped. - * Check this early, though it's not synchronized. - * utrace_add_engine() will do the final check. - */ - if (!(flags & UTRACE_ATTACH_CREATE)) - return ERR_PTR(-ENOENT); - return ERR_PTR(-ESRCH); - } + /* + * If it already could be getting reaped, we cannot attach now. + * The barrier ensures this check precedes utrace_add_engine() + * setting ->utrace_flags. tracehook_prepare_release_task() has + * the corresponding barrier, after setting EXIT_DEAD and before + * checking ->utrace_flags to decide to call utrace_release_task(). + */ + ret = target->exit_state; + smp_mb(); + + if (unlikely(ret == EXIT_DEAD)) + return ERR_PTR((flags & UTRACE_ATTACH_CREATE) ? + -ESRCH : -ENOENT); if (!(flags & UTRACE_ATTACH_CREATE)) { spin_lock(&utrace->lock); From roland at redhat.com Mon Sep 7 20:57:55 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 7 Sep 2009 13:57:55 -0700 (PDT) Subject: [PATCH 3/4] utrace_reap: do not play with lock/unlock/restart In-Reply-To: Oleg Nesterov's message of Sunday, 6 September 2009 15:50:53 +0200 <20090906135053.GA24960@redhat.com> References: <20090906134459.GA24708@redhat.com> <20090906135053.GA24960@redhat.com> Message-ID: <20090907205755.1A97E8BEBC@magilla.sf.frob.com> (Note I'm replying to 3/4 before 2/4.) > IOW, nobody change change engine->ops or REAP bit in flags. Nobody can > add the new engine or remove it from ->attached. We can do all work > lockless and without barriers. Makes sense. In commit ac6e19c the body looks like this: { struct utrace_engine *engine, *next; BUG_ON(!utrace->reap); splice_attaching(utrace); /* * Since we were called with @utrace->reap set, nobody can * set/clear UTRACE_EVENT(REAP) in @engine->flags or change * @engine->ops, and nobody can change @utrace->attached. */ spin_unlock(&utrace->lock); list_for_each_entry_safe(engine, next, &utrace->attached, entry) { if (engine->flags & UTRACE_EVENT(REAP)) engine->ops->report_reap(engine, target); engine->ops = NULL; engine->flags = 0; list_del_init(&engine->entry); utrace_engine_put(engine); } } > Note that I changed the logic a bit, we set ->ops = NULL after > ->report_reap(). Is it OK? If not, it is trivial to change. I believe this only affects utrace_barrier. See the next reply about that. Can you think of another effect? Thanks, Roland From roland at redhat.com Mon Sep 7 21:10:03 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 7 Sep 2009 14:10:03 -0700 (PDT) Subject: [PATCH 2/4] utrace_reap: do not play with ->reporting In-Reply-To: Oleg Nesterov's message of Sunday, 6 September 2009 15:44:56 +0200 <20090906134456.GA24701@redhat.com> References: <20090906134456.GA24701@redhat.com> Message-ID: <20090907211003.B7D1D8BECC@magilla.sf.frob.com> > But more importantly, I think utrace_reap() never needs to synchronize > with utrace_barrier(). Once we drop utrace->lock, any other caller which > takes this lock must see both ->exit_state and utrace->reap. This means > utrace_control() or utrace_set_events() which sets/clears REAP must not > succeed. Right. So this doesn't matter for the primary original purpose of utrace_barrier, i.e.: * A successful return from utrace_barrier() guarantees its ordering * with respect to utrace_set_events() and utrace_control() calls. But IMHO it would be nice (and the least surprising thing) if this statement were really true too: * A return value of zero means no callback from @target to @engine was * in progress. Since commit ac6e19c (my equivalent to your 3/4), utrace_barrier will no longer return -ESRCH while your report_reap callback might be running. I think its doing so before was not really ideal, because it still gave no positive indication that the callback *couldn't* still be running, which is what a caller of utrace_barrier is really there for. It seems best to me that utrace_barrier block while the engine's report_reap callback could be running, just like for all other callbacks. Then a 0 return means unequivocally that no callback is in progress, and so does an -ESRCH return. So maybe we want this? I'm not really sure about the barriers, maybe we don't need both or any at all. My thinking about that is just to keep uniform across all callbacks what kind of guarantees the caller of utrace_barrier has about the ordering of any effects its report_reap callback can have. Other callbacks always have an smp_mb() between setting ->reporting and calling the engine's code. Thanks, Roland diff --git a/kernel/utrace.c b/kernel/utrace.c index 6036764..3bec3be 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -426,8 +426,19 @@ static void utrace_reap(struct task_stru spin_unlock(&utrace->lock); list_for_each_entry_safe(engine, next, &utrace->attached, entry) { - if (engine->flags & UTRACE_EVENT(REAP)) + if (engine->flags & UTRACE_EVENT(REAP)) { + /* + * These barriers order anything ->report_reap() + * does to be while ->reporting is set. That way + * any utrace_barrier() call that returns 0 is + * guaranteeing that the callback is complete. + */ + utrace->reporting = engine; + smp_mb(); engine->ops->report_reap(engine, target); + smp_mb(); + utrace->reporting = NULL; + } engine->ops = NULL; engine->flags = 0; From roland at redhat.com Mon Sep 7 21:14:13 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 7 Sep 2009 14:14:13 -0700 (PDT) Subject: Questions about utrace In-Reply-To: Ali Polatel's message of Saturday, 5 September 2009 18:01:58 +0300 <20090905150158.GG7071@harikalardiyari> References: <20090905150158.GG7071@harikalardiyari> Message-ID: <20090907211413.3A33F8BECC@magilla.sf.frob.com> > I've been writing a ptrace based sandboxing tool, called sydbox?, and I > want to explain about some of my bad experiences with ptrace and whether > utrace will fix these deficiencies. It sounds like you are doing something very similar (from the utrace/ptrace requirements perspective, at least) to the Renzo Davoli's kmview work (http://wiki.virtualsquare.org/index.php/KMview). Renzo's experiences and thoughts about ptrace and utrace and such may be the most helpful to you. Thanks, Roland From oleg at redhat.com Mon Sep 7 22:03:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 00:03:53 +0200 Subject: [PATCH 24-27] initial stop/resume changes Message-ID: <20090907220353.GA9610@redhat.com> Incomplete and untested. And: even if this is right "in general", this code will be re-factored later anyway. Just some draft and very dirty code for early review. I came to conclusion it doesn't make sense to move ptrace_set_action() and friends into ptrace_context first, it is better to introduce the new code and then kill the old one. Oleg. From oleg at redhat.com Mon Sep 7 22:03:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 00:03:57 +0200 Subject: [PATCH 24] introduce ptrace_notify_stop() Message-ID: <20090907220357.GA9614@redhat.com> Introduce ptrace_notify_stop(). It is used by utrace_stop() which currently plays with ptrace internals. Yes, this kludge is not perfect too. Until we add something more generic to utrace. --- include/linux/ptrace.h | 2 +- kernel/utrace.c | 8 ++------ kernel/ptrace.c | 9 +++++++++ 3 files changed, 12 insertions(+), 7 deletions(-) --- PU/include/linux/ptrace.h~24_PTRACE_NOTIFY_STOP 2009-09-07 19:32:21.000000000 +0200 +++ PU/include/linux/ptrace.h 2009-09-07 19:37:47.000000000 +0200 @@ -82,7 +82,7 @@ #include /* For unlikely. */ #include /* For struct task_struct. */ - +extern void ptrace_notify_stop(struct task_struct *tracee); extern long arch_ptrace(struct task_struct *child, long request, long addr, long data); extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); --- PU/kernel/utrace.c~24_PTRACE_NOTIFY_STOP 2009-09-07 17:34:23.000000000 +0200 +++ PU/kernel/utrace.c 2009-09-07 19:50:14.000000000 +0200 @@ -409,12 +409,8 @@ static void utrace_stop(struct task_stru * be done after we are in TASK_TRACED. This makes the * synchronization with ptrace_do_wait() work right. */ - if (((task->ptrace >> 16) & UTRACE_RESUME_MASK) == - UTRACE_RESUME - UTRACE_STOP) { - read_lock(&tasklist_lock); - do_notify_parent_cldstop(task, CLD_TRAPPED); - read_unlock(&tasklist_lock); - } + if (task_ptrace(task)) + ptrace_notify_stop(task); #endif schedule(); --- PU/kernel/ptrace.c~24_PTRACE_NOTIFY_STOP 2009-09-07 17:33:08.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-07 19:48:41.000000000 +0200 @@ -898,6 +898,15 @@ static int ptrace_setsiginfo(struct task #define is_sysemu_singlestep(request) 0 #endif +void ptrace_notify_stop(struct task_struct *tracee) +{ + if (ptrace_resume_action(tracee) == UTRACE_STOP) { + read_lock(&tasklist_lock); + do_notify_parent_cldstop(tracee, CLD_TRAPPED); + read_unlock(&tasklist_lock); + } +} + static int ptrace_resume(struct task_struct *child, long request, long data) { struct utrace_engine *engine; From oleg at redhat.com Mon Sep 7 22:04:06 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 00:04:06 +0200 Subject: [PATCH 25] introduce context->stopped_code Message-ID: <20090907220406.GA9625@redhat.com> Consider, say, report_syscall_exit(). UTRACE_STOP as a return value is "useless", we could return UTRACE_REPORT or UTRACE_INTERRUPT instead. We need to record the fact we want to stop, then ->report_quiesce() or ->report_interrupt() should re-assert UTRACE_STOP. Introduce context->stopped_code. It will be set by the callback when we want to stop. Change quiesce/interrupt callbacks to check this flag and return UTRACE_STOP if it is set. Another reason for ->stopped_code is that do_wait() needs ->exit_code. So the new member is not a boolean, the callback should set the correct code which will be reported to ->parent. Change ptrace_notify_stop() to set tracee->exit_code = context->stopped_code and clear it. (this patch adds some forbidden "// XXX" comments to mark the soon to be killed code). --- kernel/ptrace.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) --- PU/kernel/ptrace.c~25_CTX_STOP_PENDING 2009-09-07 19:48:41.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-07 22:12:41.000000000 +0200 @@ -26,6 +26,8 @@ struct ptrace_context { int options; + + int stopped_code; }; static inline struct ptrace_context * @@ -392,6 +394,14 @@ static u32 ptrace_report_signal(u32 acti const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { + struct ptrace_context *context = ptrace_context(engine); + + if (context->stopped_code) { + action = utrace_signal_action(action); + WARN_ON(action != UTRACE_SIGNAL_REPORT); + return action | UTRACE_STOP; + } + switch (utrace_signal_action(action)) { default: WARN_ON(ptrace_stop_event(task) && info->si_signo != SIGKILL); @@ -431,6 +441,11 @@ static u32 ptrace_report_quiesce(u32 act struct task_struct *task, unsigned long event) { + struct ptrace_context *context = ptrace_context(engine); + + if (context->stopped_code) + return UTRACE_STOP; + if (event == 0) { task->last_siginfo = NULL; @@ -900,6 +915,28 @@ static int ptrace_setsiginfo(struct task void ptrace_notify_stop(struct task_struct *tracee) { + struct utrace_engine *engine; + struct ptrace_context *context; + + engine = utrace_attach_task(tracee, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (IS_ERR(engine)) { + // XXX: temporary check, wrong with mutlitracing + WARN_ON(tracee->state != TASK_RUNNING); + return; + } + + context = ptrace_context(engine); + if (context->stopped_code) { + tracee->exit_code = context->stopped_code; + context->stopped_code = 0; + + read_lock(&tasklist_lock); + do_notify_parent_cldstop(tracee, CLD_TRAPPED); + read_unlock(&tasklist_lock); + } + + // XXX: will die soon if (ptrace_resume_action(tracee) == UTRACE_STOP) { read_lock(&tasklist_lock); do_notify_parent_cldstop(tracee, CLD_TRAPPED); From oleg at redhat.com Mon Sep 7 22:04:08 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 00:04:08 +0200 Subject: [PATCH 26] introduce context->resume_stopped() Message-ID: <20090907220408.GA9628@redhat.com> Note! I am not sure context->resume_stopped() is good idea. Perhaps it will die, but currently it should help to convert the code. When callback wants to stop we already know what should be done to resume after stop. A callback should set ->resume_stopped which will be used later by ptrace_resume(). See the next patch as an example. --- kernel/ptrace.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) --- PU/kernel/ptrace.c~26_CTX_RESUME 2009-09-07 22:12:41.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-07 22:52:39.000000000 +0200 @@ -24,10 +24,14 @@ #include #include +typedef void (*resume_stopped_t)(struct utrace_engine *, + struct task_struct*, long); + struct ptrace_context { int options; int stopped_code; + resume_stopped_t resume_stopped; }; static inline struct ptrace_context * @@ -991,13 +995,22 @@ static int ptrace_resume(struct task_str } if (!ret) { + int event; + + if (context->resume_stopped) { + resume_stopped_t resume = context->resume_stopped; + context->resume_stopped = NULL; + WARN_ON(context->stopped_code); + resume(engine, child, data); + } + /* * If there was a non-signal event reported last time, * we may need to simulate another event that follows * it, or do some other special case. We'll set @event * nonzero here if there is an event to simulate. */ - int event = ptrace_stop_event(child); + event = ptrace_stop_event(child); ptrace_set_stop_event(child, 0); switch (event) { From oleg at redhat.com Mon Sep 7 22:04:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 00:04:12 +0200 Subject: [PATCH 27] convert ptrace_report_syscall_exit() to use ptrace_context Message-ID: <20090907220412.GA9635@redhat.com> Convert ptrace_report_syscall_exit() to use ptrace_context. Incomplete: - I don't underastand SYSEMU/SINGLESTEP magic yet - last_siginfo logic is not supported yet, but afaics the current is wrong too. --- kernel/ptrace.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) --- PU/kernel/ptrace.c~27_SYSCALL_EXIT 2009-09-07 22:52:39.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-07 23:50:50.000000000 +0200 @@ -316,24 +316,51 @@ static u32 ptrace_report_vfork_done(stru task->ptrace_message); } +static void ptrace_wake_up(struct utrace_engine *engine, + struct task_struct *tracee, + enum utrace_resume_action action) +{ + /* preserve the compatibility bug */ + if (task_is_stopped(tracee)) { + spin_lock_irq(&tracee->sighand->siglock); + tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; + spin_unlock_irq(&tracee->sighand->siglock); + } + + // XXX: FIXME!!! racy. + tracee->exit_code = 0; + + utrace_control(tracee, engine, action); +} + +static void ptrace_resume_syscall(struct utrace_engine *engine, + struct task_struct *tracee, long data) +{ + if (data) { + // XXX: until do_send_sig_info() + read_lock(&tasklist_lock); + if (tracee->signal) + send_sig(data, tracee, 1); + read_unlock(&tasklist_lock); + } + + ptrace_wake_up(engine, tracee, UTRACE_RESUME); +} + static u32 ptrace_report_syscall_exit(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *task, struct pt_regs *regs) { - if (unlikely(ptrace_stop_event(task) == PTRACE_EVENT_VFORK)) - return ptrace_report_vfork_done(task); + struct ptrace_context *context = ptrace_context(engine); - if (unlikely(ptrace_syscall_action(task)) && - unlikely(ptrace_resume_action(task) == UTRACE_SINGLESTEP)) - /* - * This is PTRACE_SYSEMU_SINGLESTEP. - * Kludge: Prevent arch code from sending a SIGTRAP - * after tracehook_report_syscall_exit() returns. - */ - user_disable_single_step(task); + WARN_ON(context->resume_stopped); + WARN_ON(context->stopped_code); - return ptrace_report_syscall(0, engine, task); + context->resume_stopped = ptrace_resume_syscall; + context->stopped_code = (context->options & PTRACE_O_TRACESYSGOOD) ? + (SIGTRAP | 0x80) : SIGTRAP; + return action | UTRACE_STOP; } static u32 ptrace_resumed(struct task_struct *task, From oleg at redhat.com Mon Sep 7 22:06:45 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 00:06:45 +0200 Subject: [PATCH 4/4] utrace_release_task: check REAP before utrace_reap() In-Reply-To: <20090907201741.3A2DE8BEBC@magilla.sf.frob.com> References: <20090906134502.GA24711@redhat.com> <20090907201741.3A2DE8BEBC@magilla.sf.frob.com> Message-ID: <20090907220645.GA9681@redhat.com> On 09/07, Roland McGrath wrote: > > In the original code, utrace_release_task() would not be called at all when > there are no engines attached. IMHO that is the optimization we want to > get back to. > > It may still be too early in the morning for me to be thinking clearly. and too late for me ;) will reply tomorrow. Oleg. > diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h > index e249770..0000000 100644 > --- a/include/linux/tracehook.h > +++ b/include/linux/tracehook.h > @@ -362,7 +362,12 @@ static inline void tracehook_report_vfor > */ > static inline void tracehook_prepare_release_task(struct task_struct *task) > { > - utrace_release_task(task); > + /* > + * See kernel/utrace.c:utrace_attach_task() about this barrier. > + */ > + smp_mb(); > + if (task_utrace_flags(task)) > + utrace_release_task(task); > } > > /** > diff --git a/kernel/utrace.c b/kernel/utrace.c > index 76d0d84..0000000 100644 > --- a/kernel/utrace.c > +++ b/kernel/utrace.c > @@ -143,13 +143,13 @@ static int utrace_add_engine(struct task > > spin_lock(&utrace->lock); > > - if (utrace->reap) { > + if (unlikely(utrace->reap)) { > /* > * Already entered utrace_release_task(), cannot attach now. > */ > ret = -ESRCH; > } else if ((flags & UTRACE_ATTACH_EXCLUSIVE) && > - unlikely(matching_engine(utrace, flags, ops, data))) { > + unlikely(matching_engine(utrace, flags, ops, data))) { > ret = -EEXIST; > } else { > /* > @@ -216,16 +216,19 @@ struct utrace_engine *utrace_attach_task > > utrace = &target->utrace; > > - if (unlikely(target->exit_state == EXIT_DEAD)) { > - /* > - * The target has already been reaped. > - * Check this early, though it's not synchronized. > - * utrace_add_engine() will do the final check. > - */ > - if (!(flags & UTRACE_ATTACH_CREATE)) > - return ERR_PTR(-ENOENT); > - return ERR_PTR(-ESRCH); > - } > + /* > + * If it already could be getting reaped, we cannot attach now. > + * The barrier ensures this check precedes utrace_add_engine() > + * setting ->utrace_flags. tracehook_prepare_release_task() has > + * the corresponding barrier, after setting EXIT_DEAD and before > + * checking ->utrace_flags to decide to call utrace_release_task(). > + */ > + ret = target->exit_state; > + smp_mb(); > + > + if (unlikely(ret == EXIT_DEAD)) > + return ERR_PTR((flags & UTRACE_ATTACH_CREATE) ? > + -ESRCH : -ENOENT); > > if (!(flags & UTRACE_ATTACH_CREATE)) { > spin_lock(&utrace->lock); From oleg at redhat.com Mon Sep 7 22:35:19 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 00:35:19 +0200 Subject: [PATCH 26] introduce context->resume_stopped() In-Reply-To: <20090907220408.GA9628@redhat.com> References: <20090907220408.GA9628@redhat.com> Message-ID: <20090907223519.GA14312@redhat.com> On 09/08, Oleg Nesterov wrote: > > A callback should set ->resume_stopped which will > be used later by ptrace_resume(). ptrace_resume() should return after calling ->resume_stopped(), updated patch below. But once again, this all needs more fixes. ------------------------------------------------------------------- [PATCH 26] introduce context->resume_stopped() Note! I am not sure context->resume_stopped() is good idea. Perhaps it will die, but currently it should help to convert the code. When callback wants to stop we already know what should be done to resume after stop. A callback should set ->resume_stopped which will be used later by ptrace_resume(). See the next patch as an example. --- kernel/ptrace.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) --- PU/kernel/ptrace.c~26_CTX_RESUME 2009-09-07 22:12:41.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-08 00:30:19.000000000 +0200 @@ -24,10 +24,14 @@ #include #include +typedef void (*resume_stopped_t)(struct utrace_engine *, + struct task_struct*, long); + struct ptrace_context { int options; int stopped_code; + resume_stopped_t resume_stopped; }; static inline struct ptrace_context * @@ -991,13 +995,24 @@ static int ptrace_resume(struct task_str } if (!ret) { + int event; + + if (context->resume_stopped) { + resume_stopped_t resume = context->resume_stopped; + context->resume_stopped = NULL; + WARN_ON(context->stopped_code); + resume(engine, child, data); + utrace_engine_put(engine); + return 0; + } + /* * If there was a non-signal event reported last time, * we may need to simulate another event that follows * it, or do some other special case. We'll set @event * nonzero here if there is an event to simulate. */ - int event = ptrace_stop_event(child); + event = ptrace_stop_event(child); ptrace_set_stop_event(child, 0); switch (event) { From ananth at in.ibm.com Tue Sep 8 05:30:25 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Tue, 8 Sep 2009 11:00:25 +0530 Subject: Questions about utrace In-Reply-To: <20090907131926.GB1513@harikalardiyari.ev> References: <20090905150158.GG7071@harikalardiyari> <20090907062608.GB3994@in.ibm.com> <20090907131926.GB1513@harikalardiyari.ev> Message-ID: <20090908053024.GC3994@in.ibm.com> On Mon, Sep 07, 2009 at 04:24:08PM +0300, Ali Polatel wrote: > Ananth N Mavinakayanahalli yazm??: > > On Sat, Sep 05, 2009 at 06:01:58PM +0300, Ali Polatel wrote: > > I've just checked it out and the interface looks a lot cleaner. > I'm really impressed, thanks for the hard work! > Are there any assumptions when utrace will be merged? Oleg and Roland are working at putting together all the code needed for the upstream merge as we speak. I don't think anybody can give you a definitive answer of when utrace will be merged. Ananth From srikar at linux.vnet.ibm.com Tue Sep 8 12:12:29 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Tue, 8 Sep 2009 17:42:29 +0530 Subject: [PATCH] Fix a race in Uprobes while removing a breakpoint Message-ID: <20090908121229.GB2900@linux.vnet.ibm.com> Fix a race where trap instruction is executed and active_ppt is not yet set and the probepoint in question is removed. A thread could execute a trap instruction resulting in SIGTRAP to be sent to the process. However before this signal is handled, the breakpoint could be removed. The core of report_signal(i.e after it write locks uproc), checks to find that there is no corresponding breakpoint structure and assumes SIGTRAP to be because of other reasons. This can cause the process to die. For more context please read the thread at https://www.redhat.com/archives/utrace-devel/2009-September/msg00028.html This patch fixes the problem at breakpoint removal time. Patch adjusts instruction pointer for those threads that have executed the trap instruction but have not yet singlestepped Signed-off-by: Srikar Dronamraju --- kernel/uprobes_core.c | 41 ++++++++++++++++++++++++++++++++--------- 1 files changed, 32 insertions(+), 9 deletions(-) diff --git a/kernel/uprobes_core.c b/kernel/uprobes_core.c index 27c2977..372325b 100644 --- a/kernel/uprobes_core.c +++ b/kernel/uprobes_core.c @@ -214,21 +214,42 @@ static void uprobe_insert_bkpt(struct uprobe_probept *ppt, } /* + * Check if task has just stepped on a trap instruction at the + * indicated address. If it has indeed stepped on that address, + * then reset Instruction Pointer for the task. + * + * tsk should either be current thread or already quiesced thread. + */ +static inline void reset_thread_ip(struct task_struct *tsk, + struct pt_regs *regs, unsigned long addr) +{ + if ((ubp_get_bkpt_addr(regs) == addr) && + !test_tsk_thread_flag(tsk, TIF_SINGLESTEP)) + ubp_set_ip(regs, addr); +} + +/* * ppt's breakpoint has been removed. If any threads are in the middle of * single-stepping at this probepoint, fix things up so they can proceed. + * If any threads have just hit breakpoint but are yet to start + * pre-processing, reset their instruction pointers. + * * Runs with all of ppt->uproc's threads quiesced and ppt->uproc->rwsem * write-locked */ -static inline void adjust_ip_active_ppt(struct uprobe_probept *ppt) +static inline void adjust_trapped_thread_ip(struct uprobe_probept *ppt) { -#ifdef CONFIG_UBP_XOL struct uprobe_process *uproc = ppt->uproc; struct uprobe_task *utask; struct pt_regs *regs; list_for_each_entry(utask, &uproc->thread_list, list) { - if (utask->active_probe != ppt) + regs = task_pt_regs(utask->tsk); + if (utask->active_probe != ppt) { + reset_thread_ip(utask->tsk, regs, ppt->ubp.vaddr); continue; + } + /* * Current thread cannot have an active breakpoint * and still request for a breakpoint removal. The @@ -236,15 +257,15 @@ static inline void adjust_ip_active_ppt(struct uprobe_probept *ppt) */ BUG_ON(utask->tsk == current); - regs = task_pt_regs(utask->tsk); +#ifdef CONFIG_UBP_XOL if (instruction_pointer(regs) == ppt->ubp.xol_vaddr) /* adjust the ip to breakpoint addr. */ ubp_set_ip(regs, ppt->ubp.vaddr); else /* adjust the ip to next instruction. */ uprobe_post_ssout(utask, ppt, regs); - } #endif + } } static void uprobe_remove_bkpt(struct uprobe_probept *ppt, @@ -264,9 +285,8 @@ static void uprobe_remove_bkpt(struct uprobe_probept *ppt, * breakpoint is hit. */ } - if (!(ppt->ubp.strategy & UBP_HNT_INLINE)) - adjust_ip_active_ppt(ppt); - else { + adjust_trapped_thread_ip(ppt); + if (ppt->ubp.strategy & UBP_HNT_INLINE) { unsigned long flags; spin_lock_irqsave(&ppt->ssil_lock, flags); ppt->ssil_state = SSIL_DISABLE; @@ -1300,8 +1320,10 @@ static void uprobe_pre_ssin(struct uprobe_task *utask, { unsigned long flags; - if (unlikely(ppt->ssil_state == SSIL_DISABLE)) + if (unlikely(ppt->ssil_state == SSIL_DISABLE)) { + reset_thread_ip(utask->tsk, regs, ppt->ubp.vaddr); return; + } spin_lock_irqsave(&ppt->ssil_lock, flags); while (ppt->ssil_state == SSIL_SET) { spin_unlock_irqrestore(&ppt->ssil_lock, flags); @@ -1316,6 +1338,7 @@ static void uprobe_pre_ssin(struct uprobe_task *utask, * been removed. Thread continues as if nothing happened. */ spin_unlock_irqrestore(&ppt->ssil_lock, flags); + reset_thread_ip(utask->tsk, regs, ppt->ubp.vaddr); return; } ppt->ssil_state = SSIL_SET; From info at canal-marketing.com Tue Sep 8 14:25:00 2009 From: info at canal-marketing.com (=?ISO-8859-1?Q?Decision_MD?=) Date: Tue, 08 Sep 2009 16:25:00 +0200 Subject: La solution pour des e-mailings efficaces Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Tue Sep 8 17:38:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 19:38:26 +0200 Subject: [PATCH 4/4] utrace_release_task: check REAP before utrace_reap() In-Reply-To: <20090907201741.3A2DE8BEBC@magilla.sf.frob.com> References: <20090906134502.GA24711@redhat.com> <20090907201741.3A2DE8BEBC@magilla.sf.frob.com> Message-ID: <20090908173826.GA7171@redhat.com> On 09/07, Roland McGrath wrote: > > --- a/include/linux/tracehook.h > +++ b/include/linux/tracehook.h > @@ -362,7 +362,12 @@ static inline void tracehook_report_vfor > */ > static inline void tracehook_prepare_release_task(struct task_struct *task) > { > - utrace_release_task(task); > + /* > + * See kernel/utrace.c:utrace_attach_task() about this barrier. > + */ > + smp_mb(); > + if (task_utrace_flags(task)) > + utrace_release_task(task); I think we can do this optimization, but see below. > + * If it already could be getting reaped, we cannot attach now. > + * The barrier ensures this check precedes utrace_add_engine() > + * setting ->utrace_flags. tracehook_prepare_release_task() has > + * the corresponding barrier, after setting EXIT_DEAD and before > + * checking ->utrace_flags to decide to call utrace_release_task(). > + */ > + ret = target->exit_state; > + smp_mb(); > + > + if (unlikely(ret == EXIT_DEAD)) > + return ERR_PTR((flags & UTRACE_ATTACH_CREATE) ? No, I think this can't work. The problem is, release and attach pathes set/check exit_state and utrace_flags in the same order, mb() can't help. release: ->exit_state = EXIT_DEAD; mb(); if (->utrace_flags) utrace_release_task(); utrace_attach_task: if (->exit_state) return -ERR; mb(); ->utrace_flags |= REAP; Even simpler, imagine that attach checks ->exit_state == 0, then the task exits and utrace_release_task() is called. I need to re-check, but afaics we can do something like the patch below. utrace_add_engine() sets REAP and _then_ checks exit_state. This way, if we race with release path, either tracehook_prepare_release_task() must notice REAP, or utrace_add_engine() must see EXIT_DEAD. But. In any case, I always dreamed to kill the current EXIT_DEAD check in utrace_attach_task. Like the previous EXIT_DEAD check which we already killed, it buys nothing imho but complicates the code. This case is very unlikely and the check is not needed for correctness. IOW, this check just slowns down the likely case. Oleg. --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -139,7 +139,7 @@ static int utrace_add_engine(struct task const struct utrace_engine_ops *ops, void *data) { - int ret; + int ret = 0; spin_lock(&utrace->lock); @@ -168,10 +168,19 @@ static int utrace_add_engine(struct task * In case we had no engines before, make sure that * utrace_flags is not zero. */ - target->utrace_flags |= UTRACE_EVENT(REAP); - list_add_tail(&engine->entry, &utrace->attaching); - utrace->pending_attach = 1; - ret = 0; + if (!target->utrace_flags) { + target->utrace_flags = UTRACE_EVENT(REAP); + smp_mb(); + if (unlikely(target->exit_state == EXIT_DEAD)) { + target->utrace_flags = 0; + ret = -ESRCH; + } + } + + if (!ret) { + list_add_tail(&engine->entry, &utrace->attaching); + utrace->pending_attach = 1; + } } spin_unlock(&utrace->lock); From oleg at redhat.com Tue Sep 8 18:08:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 20:08:17 +0200 Subject: [PATCH 3/4] utrace_reap: do not play with lock/unlock/restart In-Reply-To: <20090907205755.1A97E8BEBC@magilla.sf.frob.com> References: <20090906134459.GA24708@redhat.com> <20090906135053.GA24960@redhat.com> <20090907205755.1A97E8BEBC@magilla.sf.frob.com> Message-ID: <20090908180817.GA9070@redhat.com> On 09/07, Roland McGrath wrote: > > Makes sense. In commit ac6e19c the body looks like this: > { > struct utrace_engine *engine, *next; > > BUG_ON(!utrace->reap); > > splice_attaching(utrace); > > /* > * Since we were called with @utrace->reap set, nobody can > * set/clear UTRACE_EVENT(REAP) in @engine->flags or change > * @engine->ops, and nobody can change @utrace->attached. > */ > spin_unlock(&utrace->lock); > > list_for_each_entry_safe(engine, next, &utrace->attached, entry) { > if (engine->flags & UTRACE_EVENT(REAP)) > engine->ops->report_reap(engine, target); > > engine->ops = NULL; > engine->flags = 0; > list_del_init(&engine->entry); > > utrace_engine_put(engine); Agreed! No need to delay utrace_engine_put(). > I believe this only affects utrace_barrier. See the next reply about that. OK, > Can you think of another effect? No... I think this should be fine. It looks a bit tidier to me. Because, if we clear ->ops first, this looks as if we have a reason to clear ->ops before ->report_reap(). That is why I asked "is ot ok?", I was afraid I missed something subtle. Oleg. From oleg at redhat.com Tue Sep 8 18:39:20 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 20:39:20 +0200 Subject: [PATCH 2/4] utrace_reap: do not play with ->reporting In-Reply-To: <20090907211003.B7D1D8BECC@magilla.sf.frob.com> References: <20090906134456.GA24701@redhat.com> <20090907211003.B7D1D8BECC@magilla.sf.frob.com> Message-ID: <20090908183920.GB9070@redhat.com> On 09/07, Roland McGrath wrote: > > > But more importantly, I think utrace_reap() never needs to synchronize > > with utrace_barrier(). Once we drop utrace->lock, any other caller which > > takes this lock must see both ->exit_state and utrace->reap. This means > > utrace_control() or utrace_set_events() which sets/clears REAP must not > > succeed. > > Right. So this doesn't matter for the primary original purpose of > utrace_barrier, i.e.: > > * A successful return from utrace_barrier() guarantees its ordering > * with respect to utrace_set_events() and utrace_control() calls. Yes. > But IMHO it would be nice (and the least surprising thing) if this > statement were really true too: > > * A return value of zero means no callback from @target to @engine was > * in progress. I was going to write that this doesn't make real sense, but now I think you are right. For example, something_t *ptr; void my_report_reap(...) { if (ptr) dereference(ptr); } ... void *tmp = ptr; ptr = NULL; utrace_barrier(my_engine); kfree(tmp); With or without recent changes, this doesn't work. > I'm not really sure about the barriers, Me too. In fact, recently I realized I don't really understand the barriers around ->reporting, need to read this code with a fresh head. In particular, I'd like to see 1. Can't we set ->reporting _after_ checking engine->flags ? (unlikely) 2. Is utrace_barrier() correct???? Note the example above, it assumes that utrace_barrier() itself is the barrier wrt reporting. But, is it? > list_for_each_entry_safe(engine, next, &utrace->attached, entry) { > - if (engine->flags & UTRACE_EVENT(REAP)) > + if (engine->flags & UTRACE_EVENT(REAP)) { > + /* > + * These barriers order anything ->report_reap() > + * does to be while ->reporting is set. That way > + * any utrace_barrier() call that returns 0 is > + * guaranteeing that the callback is complete. > + */ > + utrace->reporting = engine; > + smp_mb(); > engine->ops->report_reap(engine, target); > + smp_mb(); > + utrace->reporting = NULL; Agreed. And yes, now it is important to clear ->ops _after_ calling ->report_reap(), otherwise utrace_barrier() can take the lock. Oleg. From oleg at redhat.com Tue Sep 8 19:52:47 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 21:52:47 +0200 Subject: [PATCH 1/2] utrace_attach_task: do no check ->exit_state Message-ID: <20090908195247.GA16420@redhat.com> This check is not needed for correctness and racy anyway. I also slow downs the likely case. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) --- __UTRACE/kernel/utrace.c~1_ATTACH_DONT_CK_DEAD 2009-09-08 18:15:38.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-08 20:48:56.000000000 +0200 @@ -210,23 +210,10 @@ struct utrace_engine *utrace_attach_task struct task_struct *target, int flags, const struct utrace_engine_ops *ops, void *data) { - struct utrace *utrace; + struct utrace *utrace = task_utrace_struct(target); struct utrace_engine *engine; int ret; - utrace = &target->utrace; - - if (unlikely(target->exit_state == EXIT_DEAD)) { - /* - * The target has already been reaped. - * Check this early, though it's not synchronized. - * utrace_add_engine() will do the final check. - */ - if (!(flags & UTRACE_ATTACH_CREATE)) - return ERR_PTR(-ENOENT); - return ERR_PTR(-ESRCH); - } - if (!(flags & UTRACE_ATTACH_CREATE)) { spin_lock(&utrace->lock); engine = matching_engine(utrace, flags, ops, data); From oleg at redhat.com Tue Sep 8 19:52:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 21:52:51 +0200 Subject: [PATCH 2/2] change attach/release to avoid unnecessary utrace_reap() Message-ID: <20090908195251.GA16428@redhat.com> While this is not documented explicitely (afaik), the kernel depends on store-mb-load behavior. Just for example, CPU_0: current->state = TASK_INTERRUPTIBLE; mb(); if (!COND) schedule(); vs CPU_1: COND = 1; wake_up_process(task); mb(); // <---- implicit if (task->state == TASK_RUNNING) return; ... task->state = TASK_RUNNING; should always work. Either CPU_0 must see the condition, or wakeup must see task->state. IOW, if we have A == B == 0, then CPU_0 CPU_1 A = 1; B = 1 mb(); mb(); if (B) if (A) printk("OK"); printk("OK"); "OK" should be printed at least once when both CPUs pass this code. This means we can avoid utrace_release_task() when there are no attached engines. With this patch we have: attach: task->utrace_flags = REAP; mb(); if (task->exit_state == EXIT_DEAD) abort; add the new engine release: task->exit_state = exit_DEAD; mb(); if (task->utrace_flags) utrace_release_task(); Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 5 ++++- kernel/utrace.c | 26 ++++++++++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) --- __UTRACE/include/linux/tracehook.h~2_DONT_REAP_UNCONDITIONALLY 2009-08-04 19:48:28.000000000 +0200 +++ __UTRACE/include/linux/tracehook.h 2009-09-08 20:58:53.000000000 +0200 @@ -362,7 +362,10 @@ static inline void tracehook_report_vfor */ static inline void tracehook_prepare_release_task(struct task_struct *task) { - utrace_release_task(task); + /* see utrace_add_engine() about this barrier */ + smp_mb(); + if (task_utrace_flags(task)) + utrace_release_task(task); } /** --- __UTRACE/kernel/utrace.c~2_DONT_REAP_UNCONDITIONALLY 2009-09-08 20:48:56.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-08 21:10:23.000000000 +0200 @@ -139,7 +139,7 @@ static int utrace_add_engine(struct task const struct utrace_engine_ops *ops, void *data) { - int ret; + int ret = 0; spin_lock(&utrace->lock); @@ -149,7 +149,7 @@ static int utrace_add_engine(struct task */ ret = -ESRCH; } else if ((flags & UTRACE_ATTACH_EXCLUSIVE) && - unlikely(matching_engine(utrace, flags, ops, data))) { + unlikely(matching_engine(utrace, flags, ops, data))) { ret = -EEXIST; } else { /* @@ -168,10 +168,24 @@ static int utrace_add_engine(struct task * In case we had no engines before, make sure that * utrace_flags is not zero. */ - target->utrace_flags |= UTRACE_EVENT(REAP); - list_add_tail(&engine->entry, &utrace->attaching); - utrace->pending_attach = 1; - ret = 0; + if (!target->utrace_flags) { + target->utrace_flags = UTRACE_EVENT(REAP); + /* + * If we race with tracehook_prepare_release_task() + * make sure that either it sees utrace_flags != 0 + * or we see exit_state == EXIT_DEAD. + */ + smp_mb(); + if (unlikely(target->exit_state == EXIT_DEAD)) { + target->utrace_flags = 0; + ret = -ESRCH; + } + } + + if (!ret) { + list_add_tail(&engine->entry, &utrace->attaching); + utrace->pending_attach = 1; + } } spin_unlock(&utrace->lock); From oleg at redhat.com Tue Sep 8 20:44:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Sep 2009 22:44:54 +0200 Subject: [PATCH 3/2] fix utrace_reset() vs release_task() theoretical race Message-ID: <20090908204454.GA19198@redhat.com> Roland, but we forgot about UTRACE_DETACH. If we check ->utrace_flags != 0 before utrace_reap(), then utrace_reset() becomes unsafe: nothing protects task/utrace form disappearing once utrace_reset() sets ->utrace_flags == 0. I am starting to think we are going to add too much subtle complications to avoid lock/unlock in release path :/ Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) --- __UTRACE/kernel/utrace.c~3_RESET_CAN_RACE_WITH_RELEASE 2009-09-08 22:21:57.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-08 22:32:44.000000000 +0200 @@ -726,8 +726,6 @@ static bool utrace_reset(struct task_str clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); } - task->utrace_flags = flags; - if (!flags) /* * No more engines, cleared out the utrace. @@ -740,7 +738,16 @@ static bool utrace_reset(struct task_str */ utrace_wakeup(task, utrace); + /* + * In theory spin_lock() doesn't imply rcu_read_lock(). + * Once we clear ->utrace_flags this task_struct can go away + * because tracehook_prepare_release_task() path does not take + * utrace->lock when ->utrace_flags == 0. + */ + rcu_read_lock(); + task->utrace_flags = flags; spin_unlock(&utrace->lock); + rcu_read_unlock(); put_detached_list(&detached); From oleg at redhat.com Tue Sep 8 22:11:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 9 Sep 2009 00:11:42 +0200 Subject: [PATCH 4/2] utrace_add_engine: cleanup Message-ID: <20090908221142.GA23555@redhat.com> On 09/08, Oleg Nesterov wrote: > > I am starting to think we are going to add too much subtle complications > to avoid lock/unlock in release path :/ Or not, I dunno. up to you. But if we do this change, I'd like to re-factor utrace_add_engine(). Mostly because "if (utrace->reap)" check should be near ->exit_state check, they both are the same thing: protect against release. OTOH, if we change utrace_reap() to clear ->utrace_flags, then utrace_add_engine() do not need to check ->reap at all. If you don't like it - just ignore, I don't have a strong feeling. To simplify the review: static int utrace_add_engine(struct task_struct *target, struct utrace *utrace, struct utrace_engine *engine, int flags, const struct utrace_engine_ops *ops, void *data) { int ret; spin_lock(&utrace->lock); ret = -EEXIST; if ((flags & UTRACE_ATTACH_EXCLUSIVE) && unlikely(matching_engine(utrace, flags, ops, data))) goto unlock; ret = -ESRCH; /* can't attach after utrace_release_task() */ if (utrace->reap) goto unlock; /* * In case we had no engines before, make sure that * utrace_flags is not zero. */ if (!target->utrace_flags) { target->utrace_flags = UTRACE_EVENT(REAP); /* * If we race with tracehook_prepare_release_task() * make sure that either it sees utrace_flags != 0 * or we see exit_state == EXIT_DEAD. */ smp_mb(); if (unlikely(target->exit_state == EXIT_DEAD)) { target->utrace_flags = 0; goto unlock; } } /* * Put the new engine on the pending ->attaching list. * Make sure it gets onto the ->attached list by the next * time it's examined. Setting ->pending_attach ensures * that start_report() takes the lock and splices the lists * before the next new reporting pass. * * When target == current, it would be safe just to call * splice_attaching() right here. But if we're inside a * callback, that would mean the new engine also gets * notified about the event that precipitated its own * creation. This is not what the user wants. */ list_add_tail(&engine->entry, &utrace->attaching); utrace->pending_attach = 1; ret = 0; unlock: spin_unlock(&utrace->lock); return ret; } Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 81 +++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 41 deletions(-) --- __UTRACE/kernel/utrace.c~4_CLEANUP_ADD_ENGINE 2009-09-08 22:32:44.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-08 23:46:10.000000000 +0200 @@ -139,55 +139,54 @@ static int utrace_add_engine(struct task const struct utrace_engine_ops *ops, void *data) { - int ret = 0; + int ret; spin_lock(&utrace->lock); - if (utrace->reap) { - /* - * Already entered utrace_release_task(), cannot attach now. - */ - ret = -ESRCH; - } else if ((flags & UTRACE_ATTACH_EXCLUSIVE) && - unlikely(matching_engine(utrace, flags, ops, data))) { - ret = -EEXIST; - } else { + ret = -EEXIST; + if ((flags & UTRACE_ATTACH_EXCLUSIVE) && + unlikely(matching_engine(utrace, flags, ops, data))) + goto unlock; + + ret = -ESRCH; + /* can't attach after utrace_release_task() */ + if (utrace->reap) + goto unlock; + /* + * In case we had no engines before, make sure that + * utrace_flags is not zero. + */ + if (!target->utrace_flags) { + target->utrace_flags = UTRACE_EVENT(REAP); /* - * Put the new engine on the pending ->attaching list. - * Make sure it gets onto the ->attached list by the next - * time it's examined. Setting ->pending_attach ensures - * that start_report() takes the lock and splices the lists - * before the next new reporting pass. - * - * When target == current, it would be safe just to call - * splice_attaching() right here. But if we're inside a - * callback, that would mean the new engine also gets - * notified about the event that precipitated its own - * creation. This is not what the user wants. - * - * In case we had no engines before, make sure that - * utrace_flags is not zero. + * If we race with tracehook_prepare_release_task() + * make sure that either it sees utrace_flags != 0 + * or we see exit_state == EXIT_DEAD. */ - if (!target->utrace_flags) { - target->utrace_flags = UTRACE_EVENT(REAP); - /* - * If we race with tracehook_prepare_release_task() - * make sure that either it sees utrace_flags != 0 - * or we see exit_state == EXIT_DEAD. - */ - smp_mb(); - if (unlikely(target->exit_state == EXIT_DEAD)) { - target->utrace_flags = 0; - ret = -ESRCH; - } - } - - if (!ret) { - list_add_tail(&engine->entry, &utrace->attaching); - utrace->pending_attach = 1; + smp_mb(); + if (unlikely(target->exit_state == EXIT_DEAD)) { + target->utrace_flags = 0; + goto unlock; } } + /* + * Put the new engine on the pending ->attaching list. + * Make sure it gets onto the ->attached list by the next + * time it's examined. Setting ->pending_attach ensures + * that start_report() takes the lock and splices the lists + * before the next new reporting pass. + * + * When target == current, it would be safe just to call + * splice_attaching() right here. But if we're inside a + * callback, that would mean the new engine also gets + * notified about the event that precipitated its own + * creation. This is not what the user wants. + */ + list_add_tail(&engine->entry, &utrace->attaching); + utrace->pending_attach = 1; + ret = 0; +unlock: spin_unlock(&utrace->lock); return ret; From oleg at redhat.com Tue Sep 8 22:39:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 9 Sep 2009 00:39:09 +0200 Subject: [PATCH 5/2] simplify utrace_add_engine() vs utrace_reap() protection Message-ID: <20090908223909.GA25475@redhat.com> Damn. I promise, this is the last patch today. Can't understand why I can't relax. Most probably I am trying to avoid utrace-ptrace work subconsciously... On 09/09, Oleg Nesterov wrote: > > OTOH, if we change utrace_reap() to clear ->utrace_flags, then > utrace_add_engine() do not need to check ->reap at all. Yes, makes sense imho. (assuming that the optimization makes sense). So, once again. This all is up to you, please feel free to ignore or redo. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) --- __UTRACE/kernel/utrace.c~5_ATTACH_DONT_CK_REAP 2009-09-08 23:46:10.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-09 00:29:21.000000000 +0200 @@ -148,14 +148,11 @@ static int utrace_add_engine(struct task unlikely(matching_engine(utrace, flags, ops, data))) goto unlock; - ret = -ESRCH; - /* can't attach after utrace_release_task() */ - if (utrace->reap) - goto unlock; /* * In case we had no engines before, make sure that * utrace_flags is not zero. */ + ret = -ESRCH; if (!target->utrace_flags) { target->utrace_flags = UTRACE_EVENT(REAP); /* @@ -414,8 +411,8 @@ static void utrace_reap(struct task_stru { struct utrace_engine *engine, *next; - BUG_ON(!utrace->reap); - + /* utrace_add_engine() checks ->utrace_flags != 0 */ + target->utrace_flags = 0; splice_attaching(utrace); /* From oleg at redhat.com Tue Sep 8 23:39:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 9 Sep 2009 01:39:40 +0200 Subject: [PATCH 1/2] utrace_wakeup: lock ->siglock directly Message-ID: <20090908233940.GA28556@redhat.com> The comment above utrace_wakeup: * Called with @utrace->lock held and @utrace->stopped set. Yes. This means the task can't go away, it should at least take utrace->lock first. No need to use lock_task_sighand(). Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) --- __UTRACE/kernel/utrace.c~6_WAKEUP_SIGLOCK 2009-09-09 00:29:21.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-09 01:29:02.000000000 +0200 @@ -657,13 +657,9 @@ static bool utrace_do_stop(struct task_s */ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) { - unsigned long irqflags; - utrace->stopped = 0; - if (!lock_task_sighand(target, &irqflags)) - return; - + spin_lock_irq(&target->sighand->siglock); if (likely(task_is_stopped_or_traced(target))) { if (target->signal->flags & SIGNAL_STOP_STOPPED || target->signal->group_stop_count) @@ -671,8 +667,7 @@ static void utrace_wakeup(struct task_st else wake_up_state(target, __TASK_STOPPED | __TASK_TRACED); } - - unlock_task_sighand(target, &irqflags); + spin_unlock_irq(&target->sighand->siglock); } /* From oleg at redhat.com Tue Sep 8 23:39:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 9 Sep 2009 01:39:43 +0200 Subject: [PATCH 2/2] utrace_wakeup: do not check target->state Message-ID: <20090908233943.GA28564@redhat.com> utrace_wakeup() is called when utrace->stopped = T. This means the task is either TASK_TRACED or killed. If it is killed, SIGNAL_STOP_STOPPED is not possible and wake_up_state(__TASK_TRACED) does nothing. No need to check task_is_stopped_or_traced(). Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) --- __UTRACE/kernel/utrace.c~7_WAKEUP_DONT_CK_STATE 2009-09-09 01:29:02.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-09 01:32:03.000000000 +0200 @@ -659,14 +659,13 @@ static void utrace_wakeup(struct task_st { utrace->stopped = 0; + /* The task must be either TASK_TRACED or killed */ spin_lock_irq(&target->sighand->siglock); - if (likely(task_is_stopped_or_traced(target))) { - if (target->signal->flags & SIGNAL_STOP_STOPPED || - target->signal->group_stop_count) - target->state = TASK_STOPPED; - else - wake_up_state(target, __TASK_STOPPED | __TASK_TRACED); - } + if (target->signal->flags & SIGNAL_STOP_STOPPED || + target->signal->group_stop_count) + target->state = TASK_STOPPED; + else + wake_up_state(target, __TASK_TRACED); spin_unlock_irq(&target->sighand->siglock); } From newsletter at rmcvisual.upmailer.com Wed Sep 9 09:25:47 2009 From: newsletter at rmcvisual.upmailer.com (RMC Visual) Date: Wed, 09 Sep 2009 13:25:47 +0400 Subject: =?utf-8?q?Tudo_o_que_necess=C3=ADta_Curitiba_e_regi=C3=A3o?= Message-ID: <6f6f5d13777545a6c843e789e316b56c@rmcvisual.upmailer.com> Seu cliente de e-mail n?o pode ler este e-mail. Para visualiz?-lo on-line, por favor, clique aqui: http://rmcvisual.upmailer.com/display.php?M=590781&C=b7ae2a4d9b72b45f6acfacec63a9af7f&S=16&L=14&N=14 Para parar de receber nossos e-mails:http://rmcvisual.upmailer.com/unsubscribe.php?M=590781&C=b7ae2a4d9b72b45f6acfacec63a9af7f&L=14&N=16 Desenvolvido por UpMailer -------------- next part -------------- An HTML attachment was scrubbed... URL: From apinto.po at gmail.com Wed Sep 9 09:37:51 2009 From: apinto.po at gmail.com (=?utf-8?B?Q2FydMO1ZXMgZGUgY3LDqWRpdG8gQ2l0aSA=?=) Date: Wed, 09 Sep 2009 12:37:51 +0300 Subject: =?utf-8?q?Adira_online_com_anuidades_gr=C3=A1tis=0D=0A?= Message-ID: <20090909100054.AF17A6390863@mta3.serverpapaia.com> Se n?o conseguir visualizar este e-mail, clique aqui: www.serverpapaia.com/citi_bank.html ----- Para deixar de receber as nossas novidades clique aqui http://www.serverpapaia.com/oem/unsubscribe.php?CampaignID=43&CampaignStatisticsID=64&Demo=0&EncryptedMemberID=MTU5NTk2NTgwMDA%3D&Email=dXRyYWNlLWRldmVsQHJlZGhhdC5jb20= -------------- next part -------------- An HTML attachment was scrubbed... URL: From internet.novidades at gmail.com Wed Sep 9 15:29:39 2009 From: internet.novidades at gmail.com (=?utf-8?B?SiZCIHByw6ltaW9zIG9ubGluZSA=?=) Date: Wed, 09 Sep 2009 17:29:39 +0200 Subject: =?utf-8?q?Habilita-te_a_ganhar_centenas_de_pr=C3=A9mios_com_J=26?= =?utf-8?q?B=0D=0A?= Message-ID: <20090909152950.2337C422801C@mta4.servergoiaba.com> Caso n?o visualize correctamente este e-mail, por favor clique no seguinte link: www.servergoiaba.com/jb.html ----- Esta mensagem ? enviada para utrace-devel at redhat.com de acordo com a legisla??o Europeia em vig?r sobre o envio de mensagens comerciais, ao abrigo da Directiva 2000/31/CE do Parlamento Europeu e Relat?rio A5-0270/2001 do Parlamento Europeu, e n?o pode ser considerado "SPAM", pois est? claramente identificada pelo seu emissor. Ao abrigo do Dec.Lei 67/98 de 26 de Outubro, o destinat?rio poder? a qualquer momento proceder ? rectifica??o ou cancelamento dos seus dados, conforme o disposto nos artigos 10? e 11?. Para deixar de receber as nossas novidades clique no seguinte link http://www.servergoiaba.com/news/unsubscribe.php?CampaignID=40&CampaignStatisticsID=41&Demo=0&EncryptedMemberID=MTUxNzEwMzEzMDQ%3D&MailLists=2&Email=dXRyYWNlLWRldmVsQHJlZGhhdC5jb20= -------------- next part -------------- An HTML attachment was scrubbed... URL: From roland at redhat.com Wed Sep 9 22:03:04 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 9 Sep 2009 15:03:04 -0700 (PDT) Subject: [PATCH 24-27] initial stop/resume changes In-Reply-To: Oleg Nesterov's message of Tuesday, 8 September 2009 00:03:53 +0200 <20090907220353.GA9610@redhat.com> References: <20090907220353.GA9610@redhat.com> Message-ID: <20090909220304.F17CB8AE5E@magilla.sf.frob.com> I merged it all. But I tend to think the function pointer is overkill. It's probably simpler and cleaner in the end to just store PTRACE_EVENT_* and have a switch, or something like that. Thanks, Roland From roland at redhat.com Wed Sep 9 22:27:32 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 9 Sep 2009 15:27:32 -0700 (PDT) Subject: [PATCH 4/4] utrace_release_task: check REAP before utrace_reap() In-Reply-To: Oleg Nesterov's message of Tuesday, 8 September 2009 19:38:26 +0200 <20090908173826.GA7171@redhat.com> References: <20090906134502.GA24711@redhat.com> <20090907201741.3A2DE8BEBC@magilla.sf.frob.com> <20090908173826.GA7171@redhat.com> Message-ID: <20090909222732.5E65D8BF69@magilla.sf.frob.com> > I think we can do this optimization, but see below. Nice work! I've merged it all. Thanks, Roland From roland at redhat.com Wed Sep 9 22:33:34 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 9 Sep 2009 15:33:34 -0700 (PDT) Subject: [PATCH 2/4] utrace_reap: do not play with ->reporting In-Reply-To: Oleg Nesterov's message of Tuesday, 8 September 2009 20:39:20 +0200 <20090908183920.GB9070@redhat.com> References: <20090906134456.GA24701@redhat.com> <20090907211003.B7D1D8BECC@magilla.sf.frob.com> <20090908183920.GB9070@redhat.com> Message-ID: <20090909223334.906AB8BF69@magilla.sf.frob.com> > 1. Can't we set ->reporting _after_ checking engine->flags ? > (unlikely) I'm not sure...it is early the morning again. ;-) > 2. Is utrace_barrier() correct???? Note the example above, > it assumes that utrace_barrier() itself is the barrier > wrt reporting. But, is it? I don't think I understand the question. > > list_for_each_entry_safe(engine, next, &utrace->attached, entry) { > > - if (engine->flags & UTRACE_EVENT(REAP)) > > + if (engine->flags & UTRACE_EVENT(REAP)) { > > + /* > > + * These barriers order anything ->report_reap() > > + * does to be while ->reporting is set. That way > > + * any utrace_barrier() call that returns 0 is > > + * guaranteeing that the callback is complete. > > + */ > > + utrace->reporting = engine; > > + smp_mb(); > > engine->ops->report_reap(engine, target); > > + smp_mb(); > > + utrace->reporting = NULL; > > Agreed. Let's verify/explain the logic of each barrier before we put it in. > And yes, now it is important to clear ->ops _after_ calling > ->report_reap(), otherwise utrace_barrier() can take the lock. Right. Thanks, Roland From oleg at redhat.com Wed Sep 9 22:30:15 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 10 Sep 2009 00:30:15 +0200 Subject: [PATCH 28] ptrace_report_syscall_exit: return UTRACE_STOP, not UTRACE_RESUME Message-ID: <20090909223015.GA14099@redhat.com> Can't resist, I am sending this as a separate patch. Because I spent 3 hours debugging, and because the number and the ordering of these changes doesn't matter. As I said, I know that these initial changes of stop/resume model need fixes, but I don't understand some failures. Will test/debug more. --- kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- PU/kernel/ptrace.c~28_SYSCALL_EXIT_FIX 2009-09-09 23:41:03.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-10 00:23:58.000000000 +0200 @@ -360,7 +360,7 @@ static u32 ptrace_report_syscall_exit(en context->resume_stopped = ptrace_resume_syscall; context->stopped_code = (context->options & PTRACE_O_TRACESYSGOOD) ? (SIGTRAP | 0x80) : SIGTRAP; - return action | UTRACE_STOP; + return UTRACE_STOP; } static u32 ptrace_resumed(struct task_struct *task, From oleg at redhat.com Wed Sep 9 23:12:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 10 Sep 2009 01:12:40 +0200 Subject: [PATCH 24-27] initial stop/resume changes In-Reply-To: <20090909220304.F17CB8AE5E@magilla.sf.frob.com> References: <20090907220353.GA9610@redhat.com> <20090909220304.F17CB8AE5E@magilla.sf.frob.com> Message-ID: <20090909231240.GA15758@redhat.com> On 09/09, Roland McGrath wrote: > > But I tend to think the function pointer is overkill. Yes, agreed. As I said, this code will be re-factored anyway. I added this pointer just because it is a bit easier to me to start the changes this way, currently I do not have the precise plan. Oleg. From cisse at cisse2009online.org Wed Sep 9 23:30:08 2009 From: cisse at cisse2009online.org (CISSE 2009) Date: Wed, 09 Sep 2009 19:30:08 -0400 Subject: Call for Papers: The 5th CISSE International Conference Message-ID: <9a9212c6f130f248eeacc4e6746604c1@www.cheapbulkmails.com> Dear Colleagues, If you received this email in error, please forward it to the appropriate department at your institution. If you wish to unsubscribe please follow the unsubscribe link at bottom of the email. Please do not reply to this message. If you need to contact us please email us at info at cisse2009online.org ********************************************************************** * The Fifth International Joint Conferences on Computer, * * Information, and Systems Sciences, and Engineering (CISSE 2009) * * * * http://www.cheapbulkmails.com/IEM/link.php?M=2027391&N=15&L=8&F=T * * * ********************************************************************** December 4-12, 2009 Sponsored by the University of Bridgeport Technically co-sponsored by the IEEE Computer Society, Communications Society and Education Society (Connecticut Section) --------------------------------------------------------------------- CONFERENCE OVERVIEW --------------------------------------------------------------------- CISSE 2009 provides a virtual forum for presentation and discussion of the state-of the-art research on computers, information and systems sciences and engineering. CISSE 2009 is the fifth conference of the CISSE series of e-conferences. CISSE is the World's first Engineering/Computing and Systems Research E-Conference. CISSE 2005 was the first high-caliber Research Conference in the world to be completely conducted online in real-time via the internet. CISSE 2005 received 255 research paper submissions and the final program included 140 accepted papers, from more than 45 countries. CISSE 2006 received 691 research paper submissions and the final program included 390 accepted papers, from more than 70 countries. CISSE 2007 received 750 research paper submissions and the final program included 406 accepted papers. A total of 948 paper submissions were received for CISSE 2008 and the final program included 382 accepted papers, from more than 80 countries. The virtual conference will be conducted through the Internet using web-conferencing tools, made available by the conference. Authors will be presenting their PowerPoint, audio or video presentations using web-conferencing tools without the need for travel. Conference sessions will be broadcast to all the conference participants, where session participants can interact with the presenter during the presentation and/or during the Q&A slot that follows the presentation. This international conference will be held entirely on-line. The accepted and presented papers will be made available and sent to the authors after the conference both on a DVD (including all papers, PowerPoint presentations and audio presentations) and as a book publication. Springer, the official publisher for CISSE, published the 2005 proceedings in 2 books and the CISSE 2006, CISSE 2007 and CISSE 2008 proceedings in four books each. Conference participants - authors, presenters and attendees - only need an internet connection and sound available on their computers in order to be able to contribute and participate in this international ground-breaking conference. The on-line structure of this high-quality event will allow academic professionals and industry participants to contribute their work and attend world-class technical presentations based on rigorously refereed submissions, live, without the need for investing significant travel funds or time out of the office. The concept and format of CISSE is ground-breaking. The PowerPoint presentations, final paper manuscripts and time schedule for live presentations over the web had been available for weeks prior to the start of the conference for all registrants, so that the participants can choose the presentations they want to attend and think about questions that they might want to ask. The live audio presentations were also recorded and are part of the permanent CISSE on-line archive - accessible to all registrants - which also includes all the papers, PowerPoint and audio presentations. Potential non-author conference attendees who cannot make the on-line conference dates are encouraged to register, as the entire joint conferences will be archived for future viewing. The CISSE conference audio room provides superb audio even over low speed internet connections, the ability to display PowerPoint presentations, and cross-platform compatibility (the conferencing software runs on Windows, Mac, and any other operating system that supports Java). In addition, the conferencing system allowed for an unlimited number of participants, which in turn granted us the opportunity to allow all CISSE participants to attend all presentations, as opposed to limiting the number of available seats for each session. Prospective authors are invited to submit full papers electronically in Microsoft Word or Adobe PDF format through the website of the conference at: http://www.cheapbulkmails.com/IEM/link.php?M=2027391&N=15&L=8&F=T Accepted papers must be presented in the virtual conference by one of the authors. To submit your paper, please visit http://www.cheapbulkmails.com/IEM/link.php?M=2027391&N=15&L=8&F=T CISSE 2009 is composed of the following four conferences: International Conference on Systems, Computing Sciences and Software Engineering (SCSS 09) Topics: Grid Computing, Internet-based Computing Models, Resource Discovery, Programming Models and tools, e-Science and Virtual Instrumentation, Biometric Authentication, Computers for People of Special Needs, Human Computer Interaction, Information and Knowledge Engineering, Algorithms, Parallel and Distributed processing, Modeling and Simulation, Services and Applications, Embedded Systems and Applications, Databases, Programming Languages, Signal Processing Theory and Methods, Signal Processing for Communication, Signal Processing Architectures and Implementation, Information Processing, Geographical Information Systems,Object Based Software Engineering, Parallel and Distributed Computing, Real Time Systems, Multiprocessing, File Systems and I/O, Kernel and OS Structures. International Conference on Telecommunications and Networking (TeNe 09) Topics: Optical Networks and Switching, Computer Networks, Network architectures and Equipment, Access Technologies, Telecommunication Technology, Coding and Modulation technique, Modeling and Simulation, Spread Spectrum and CDMA Systems, OFDM technology, Space-time Coding, Ultra Wideband Communications, Medium Access Control, Spread Spectrum, Wireless LAN: IEEE 802.11, HIPERLAN, Bluetooth, Cellular Wireless Networks, Cordless Systems and Wireless Local Loop, Mobile Network Layer, Mobile Transport Layer, Support for Mobility, Conventional Encryption and Message Confidentiality, Block Ciphers Design Principles, Block Ciphers Modes of Operation, Public-Key Cryptography and Message Authentication, Authentication Application, Stenography, Electronic Mail Security, Web Security, IP Security, Firewalls, Computer Forensics. International Conference on Engineering Education, Instructional Technology, Assessment, and E-learning (EIAE 09) Topics: Instructional Design, Accreditation, Curriculum Design, Educational Tools, 2-2-2 Platforms, Teaching Capstone Design, Teaching Design at the Lower Levels, Design and Development of e-Learning tools, Assessment Methods in Engineering, Development and Implementation of E-learning tools, Ethics in Education, Economical and Social Impacts of E-learning. International Conference on Industrial Electronics, Technology & Automation (IETA 09) Topics: Advanced and Distributed Control Systems, Intelligent Control Systems (NN, FL, GA, .etc), Expert Systems, Man Machine Interaction, Data Fusion, Factory Automation, Robotics, Motion Control, Machine Vision, MEMS Sensors and Actuators, Sensors Fusion, Power Electronics, High Frequency Converters, Motors and Drives, Power Converters, Power Devices and Components, Electric Vehicles and Intelligent Transportation, Process Automation, Factory Communication, Manufacturing Information System Advances in Manufacturing Systems, Industrial Applications of Multi Media, Intelligent Systems Instrumentation, Industrial Instrumentation, Modeling and Simulation, Signal Processing, Image and Data Processing, VR and Parallel systems. Paper Submission ================= Prospective authors are invited to submit full papers electronically in Microsoft Word or Adobe PDF format through the website of the conference at http://www.cheapbulkmails.com/IEM/link.php?M=2027391&N=15&L=8&F=T Accepted papers must be presented in the virtual conference by one of the authors. To submit your paper, please visit http://www.cheapbulkmails.com/IEM/link.php?M=2027391&N=15&L=8&F=T Paper submission Deadline: October 12th, 2009 Notification of Acceptance: November 13th, 2009 Final Manuscript and Registration: November 26th, 2009 ------------------------------------------------------------------------ S. Patel Technical Support, CISSE 2009 University of Bridgeport 221 University Avenue info at cisse2009online.org Bridgeport, CT 06604, U.S.A. http://www.cheapbulkmails.com/IEM/link.php?M=2027391&N=15&L=8&F=T ------------------------------------------------------------------------ TO UNSUBSCRIBE FROM OUR LIST AND STOP RECEVING EMAILS FROM CISSE PERMANENTLY please visit http://www.cheapbulkmails.com/IEM/link.php?M=2027391&N=15&L=9&F=T. We honor all unsubscribe requests. -------------- next part -------------- An HTML attachment was scrubbed... URL: From info at canal-marketing.com Thu Sep 10 14:05:00 2009 From: info at canal-marketing.com (=?ISO-8859-1?Q?IC_Telecom?=) Date: Thu, 10 Sep 2009 16:05:00 +0200 Subject: Illimite : Communications - Internet - telephones Message-ID: An HTML attachment was scrubbed... URL: From info at canal-direct.com Thu Sep 10 16:10:00 2009 From: info at canal-direct.com (=?ISO-8859-1?Q?Chlo=E9_DAUMAS?=) Date: Thu, 10 Sep 2009 18:10:00 +0200 Subject: S'organiser d'un seul coup d'oeil Message-ID: An HTML attachment was scrubbed... URL: From mldireto at tudoemoferta.com.br Thu Sep 10 18:20:52 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Thu, 10 Sep 2009 15:20:52 -0300 Subject: Fizemos 14 felizardos em Agosto. Confira e nao perca as proximas opotunidades Message-ID: An HTML attachment was scrubbed... URL: From Prossegur at promoportugal.net Tue Sep 8 13:40:34 2009 From: Prossegur at promoportugal.net (Prossegur) Date: Tue, 08 Sep 2009 17:40:34 +0400 Subject: Se a sua casa estivesse a ser assaltada, quando iria saber? Message-ID: <9629a38186321e1b87b564da4586afad@80.79.118.187> Em 2008, 30.000 Lares foram assaltados. Avalie j? e gr?tis a seguran?a da sua casa. N?o fique ? espera, a sua casa est? em risco. Diagn?stico Gr?tis http://80.79.118.187/iemailer/link.php?M=583068&N=16&L=23&F=T -------------- next part -------------- An HTML attachment was scrubbed... URL: From Contact2 at mail.datingprotector.com Sat Sep 12 04:45:28 2009 From: Contact2 at mail.datingprotector.com (Belinda) Date: Fri, 11 Sep 2009 22:45:28 -0600 Subject: Discount Message-ID: For utrace-devel at redhat.com: SAVE 72% off on name brand sport shoes to you. We assure you high quality, best price and speedy delivery. We also sell name brand Fashion Shoes, Handbags, Sport Clothes and other famous brands including Nike, Converse, Adidas, Puma, Kappa, Prada, Gucci, Louis Vuitton and UGG etc. Looking forward to have your inquiries. Sales Contact Sales at Foruggs.com Other discount name brand products: T-shirts, Jeans, Hats, Wallets, Belts, Sunglasses, Wig, Wrist-watches etc. From news at webrobbie.com Fri Sep 11 17:28:16 2009 From: news at webrobbie.com (Robbie - Offer for you!) Date: Fri, 11 Sep 2009 18:28:16 +0100 Subject: Robbie - Offer for you! Message-ID: <48682118438081966717403@OLGATOSH> GeeToday! Sport News All the latest sports news, scores, fantasy games, and more Breaking news, results, video, audio and analysis on football, cricket, rugby, golf, tennis, motorsport, NBA, NHL, horse, racing and all the main world sports. www.geeearth.info Hello! INTRODUCE OUR OFFER for Singers, DJs! Complete Online Small Business Website Design Solution Get your professionally-designed small business website published quickly and affordably with WebRobbie.com's CMS WEB DESIGN. Call us, and tell us about your business. In less than seven days, our small business website designers will build a functional, easy-to-navigate site with a layout that ranks your business on the search engines. All this for only 25.95 EUR per month-with no set-up fees. Do you want Subscribe, Unsubscribe utrace-devel at redhat.com? or just send me e-mail: news at webrobbie.com. Thanks! Your WEB CMS ROBBIE! package includes: Web CMS - content management system > more details Professional Small Business Website Design A detailed interview to learn about your business A professionally designed, search engine optimized website Your site is live in less than 7 days Site hosting and domain name registration Unlimited design and content changes in the first 30 days 60 minutes per month of ongoing edit and design support Easy self-editing tools 24/7 technical support Marketing and Search Engine Promotion Search engine submissions???be where your customers are searching???Google???, Yahoo!, AOL ,MSN and more Guaranteed inclusion on Yahoo! and Yahoo! powered search engines Enhanced listing in Google Maps??? including coupon capabilities Top Internet Yellow Page and local search engine directory listings Trackable toll-free number so that you never miss another phone lead Constant Contact email marketing Real-time Performance Scorecard Review up-to-the-minute and historical site traffic Customer contact leads and email prospects display and tracking Track phone calls including details about all missed calls Complete CMS WEB ROBBIE! Value Comparison web Website Design & Marketing Services CMS WEB Other Website Marketing Companies Monthly Total 75, 95 EUR /month 389, 00 EUR /month Building Your Website Professional Web Design Included 350 EUR + Professional Copywriting Included 350 EUR + Domain Name Registration Included 8.6 EUR /year Website Hosting Included 11 EUR /month Search Engine Optimization (SEO) Included 1050 EUR for 3 Pages Marketing Your Website Search Engine Submission Included 30 EUR /month Directory Submissions Included 140 EUR /submission Yahoo! Paid Inclusion Included 35 EUR /year Email Marketing Service Included 11 EUR /month Ongoing SEO Analysis Included 176 EUR /month Contact us Create Your Own Website Today. Have Your Business Online Tomorrow. Our Do-it-yourself Website Design package provides everything you need to get started. You'll get detailed instructions on how to make a website and access to thousands of design template combinations, customizable starter content and dynamic website features. Here's What You Get All Inclusive Hosting and Website Package Free Domain Name Unlimited Hosting Unlimited Web Storage Unlimited Monthly Transfer Unlimited E-Mail User Accounts With our all inclusive hosting plan, you have unlimited room to store all of your photos, videos and audio files. You'll also get e-mail accounts for all of your users and 10GB of e-mail storage. It's everything you need to build a successful web presence! Every Tool You Need to Build Your Website Do-It-Yourself Website Building Tool Thousands of professional website designs Image Library Point & Click Editing No technical experience is necessary to develop your site using our easy-to-use website building tool. With thousands of professional designs and a fully stocked image library, we make it simple for you to create and publish your own website. Extras to Make Your Site That Much Bette Guest Book, Site Search Online Polling Contact Forms Mapping Feature Have your visitors sign your online guestbook or fill out a form to contact you through your website. Plus, find out what your customers really want through an online poll. Engage your users with any or all of these great features at no additional cost to you! Do-it-yourself CMS WEB ROBBIE! SPECIAL package includes: Website Design & Marketing Services CMS WEB Other Website Marketing Companies Monthly Total 25, 95 EUR /month 113, 00 EUR /month Building Your Website Professional Web Design Included 250 EUR + Professional Copywriting Included 250 EUR + Domain Name Registration Included 8.6 EUR /year Website Hosting Included 11 EUR /month Marketing Your Website Search Engine Submission Included 30 EUR /month Directory Submissions Included 140 EUR /submission Yahoo! Paid Inclusion Included 35 EUR /year Email Marketing Service Included 11 EUR /month Ongoing SEO Analysis Included 76 EUR /month Contact us eCommerce design We Make it Easy to Sell Online You???re excited about all of the endless possibilities of a virtual store, you have the right products and you are ready to get started. You know you must be able to build, manage and expand your store whether you start with 1 or 100,000 products. But, where do you begin? The choices for the look of your store, the shopping cart functionality and the payment processing options can be mind-boggling. Let us make it easier. As you search your eCommerce options, your top criteria should include power, security and versatility. WebRobbie.com???s eCommerce solutions are easy to integrate and use, versatile enough for any size operation and fully compliant with the CISP and PCI security standards. Enter WebRobbie.comThere's no such thing as one size fits all in the competitive eCommerce marketplace ??? that's why we learn about your expectations then custom-tailor a store just for you. We deliver the right solution for your business needs and your budget. Partner with Web.com and put our professional eCommerce team to work for you. Come to WebRobbie.com if you need a little assistance or require a fully-designed store. You can add an eCommerce option to any of our WebRobbie.com website packages or simply add a store to your current website. Our eCommerce packages start as low as 59.95 EUR per month! Add eCommerce to your website. It's simple enough for beginners, but powerful enough for pros. When you partner with Web.com, we work with you to deliver the right solution for your needs and budget. Whether you want to sell one product or hundreds, we have the right package for you. There's no such thing as one size fits all in the competitive eCommerce marketplace ??? that's why we learn about your needs and expectations, then custom-tailor a solution just for you. Selling your products online has never been easier, more affordable or more profitable! All of our eCommerce solutions include: Inventory tracking and management Easy customer access to account details and addresses Automatic shipping rates from UPS, USPS, FedEx and more Credit card processing SSL security certificates Not only can we add an eCommerce storefront to any of our Web.com website packages, but we can add a custom eCommerce store to a website you already have. Our professional eCommerce website designers will work with you every step of the way, from initial development to long-term maintenance, to ensure that your site remains a success well into the future. eCommerce WEB ROBBIE! SPECIAL package includes: Website Design & Marketing Services eCommerce Do it yourself Special Offer Simple e-Shop 50 items 560 EUR /year 45 EUR /month 250 items 990 EUR /year 75 EUR /month 500 items 1350 EUR /year 75 EUR /month 1000 items 1650 EUR /year 75 EUR /month Over /year 75 EUR /month Contact us Engage visitors with a customized web site design. Our Custom web design team delivers best-in-class design expertise and the technical skills to make Custom Website Design Professional custom website design team with expertise to build high-end sites???at a fraction of the cost of other web design firms One-on-one collaboration with our custom web site design team to create an image that fits the business Speedy design and publishing within days???other custom website firms may take months to complete a site Flexible options to build with Flash web design graphics using animation to attract, engage and keep customers Ongoing and on-demand website modifications and marketing support Fully search engine optimized site???your website content is built so that the major search engines find and display your site when customers are looking for your product or service Custom Features Superior eCommerce solutions that help you easily sell your products online Numerous other options: online reporting with a toll-free number, domain registration, search engine submissions, online Yellow Page ads, Constant Contact email marketing solution Our custom website designers don't just create a great business site; we create a site for your business. You'll be impressed by our innovative, cutting-edge custom web site design and love our competitive, affordable custom web design pricing. Contact us Take a Look at These Great Examples! SINGER Ingola Online Biography and music albums. http://www.webrobbie.com/clients/INGOLA/ Sport News All the latest sports news, scores, fantasy games, and more Breaking news, results, video, audio and analysis on football, cricket, rugby, golf, tennis, motorsport, NBA, NHL, horse, racing and all the main world sports. www.geetoday.info Health: Diet & Fitness, Mind & Mood, Longevity, Conditions & Diseases, & Drug Guide Find information on wellness, diet, fitness, weight loss, mental health, anti-aging, conditions & diseases, drugs & medications, and more on Gee EYE! Health www.geeeye.com RENEWABLE ENERGY :: ENERGY DAILY NEWS :: Wind, Solar, Hydro Energy Power Clean Earth Energy News, Eco Energy Power, Green Energy, Wind Energy, Solar Energy, Hydro Energy, Home Energy, Joomla! - the dynamic portal engine and content management system. www.geeearth.info Automotive DAILY News Daily News, Reviews, Auto show, China, Hybrid, Spy, Crash test, Tips, Traffic, UK, USA, AUSTRALIA, Wallpaper, Chat, Joomla the dynamic portal engine and content management system. www.geef1.com Amero Gee! Daily News - Free Trade Agreement, NAFTA, Security Prosperity Partnership - SPP Amero Gee! Implementation countries, currency, units, U.S. Dollar, Canadian Dollar, Mexican Peso, European Union the Euro, North America, NAFTA, Security Prosperity Partnership - SPP www.amerogee.com Irish Butchers :: Mallons Foodhall IrishButchers.com :: Mallons Foodhall :: Beef, Lamb, Pork, Chicke, Seafood, BBQ, Miscellaneous, Bulk Meats, Value Packs, Pick a Pack, BBQ Packs, 50 EUR Meal Pack Bulk Meats Value Packs Pick a Pack BBQ Packs Seafood, BBQ, Miscellaneous, Lamb, Pork, Chicken, Daily Specials Mallons Sausages, Beef www.irishbutchers.com ROLL-UP Digital printing roll-up. http://www.webrobbie.com/clients/ROLLUP/ Champion Dj Services. Weddings, Birthdays, Theme nights, Corporate events, Special occasions www.championdjservices.com Leather Factory Leather Cases and leather Belts at factory discounted prices. Wholesale and retail. Custom embroidering. http://www.webrobbie.com/clients/ROBBIEOROY/ Yeah lingerie and sexy tanga online e-shop Luxury bras - Luxury short - String ??? Panties - Micro bikinis - Open Thongs - Suspender belts - Bodystocking - Babydolls ??? Chemise - Luxurie lingerie set - Luxury hosiery - Sexy luxury body - Guepiere???Bustier???Corsets - Sexy pyjamas - Night dress - Sexy Dresses - Sexy lingerie vinyl - Costumes & Makes - Gloves - Accessories www.yeahlingerie.com Web Development Flash Demo, Online Marketing. Flash Tutorials, web development ireland, web design ireland, website design dublin, online marketing ireland, website development dublin, search engine optimisation, internet usability accessibility, website hosting ireland, content management software tool dublin www.afiflash.com STIV Contraction Construction playgrounds. http://www.webrobbie.com/clients/LANDSCAPEKIDS/ Terrain Landscape Brian Landcape, Hardscapes and patios in Oakbrook, Hinsdale and surronding communities http://www.webrobbie.com/clients/LANDSCAPE/ Contact us Web Robbie COM, Los Angeles, CA - Robbie IE, Dublin, IRL ? 2009 webRobbie.com. All Rights Reserved Subscribe Subscribe or Unsubscribe -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Sat Sep 12 00:34:25 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 12 Sep 2009 02:34:25 +0200 Subject: [PATCH] move ->reporting from struct utrace to utrace_engine Message-ID: <20090912003425.GA611@redhat.com> I still need to review (and understand ;) the ->reporting logic/barriers and continue the related discussion. But can't we move ->reporting from utrace to engine? This saves a word in task_struct. Yes, this adds the same word to engine, but we should optimize the common untraced case. Or do you have other plans for utrace->reporting? Signed-off-by: Oleg Nesterov --- include/linux/utrace_struct.h | 2 -- include/linux/utrace.h | 1 + kernel/utrace.c | 38 +++++++++++++++++++------------------- 3 files changed, 20 insertions(+), 21 deletions(-) --- __UTRACE/include/linux/utrace_struct.h~1_MV_REPORTING 2009-09-08 18:15:38.000000000 +0200 +++ __UTRACE/include/linux/utrace_struct.h 2009-09-12 02:07:30.000000000 +0200 @@ -30,8 +30,6 @@ struct utrace { struct list_head attached, attaching; spinlock_t lock; - struct utrace_engine *reporting; - unsigned int stopped:1; unsigned int report:1; unsigned int interrupt:1; --- __UTRACE/include/linux/utrace.h~1_MV_REPORTING 2009-09-12 02:02:45.000000000 +0200 +++ __UTRACE/include/linux/utrace.h 2009-09-12 02:09:37.000000000 +0200 @@ -327,6 +327,7 @@ struct utrace_engine { /* public: */ const struct utrace_engine_ops *ops; + bool reporting; void *data; unsigned long flags; --- __UTRACE/kernel/utrace.c~1_MV_REPORTING 2009-09-12 02:03:21.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-09-12 02:24:27.000000000 +0200 @@ -584,14 +584,14 @@ int utrace_set_events(struct task_struct if (!utrace->stopped && target != current && !target->exit_state) { /* * This barrier ensures that our engine->flags changes - * have hit before we examine utrace->reporting, + * have hit before we examine engine->reporting, * pairing with the barrier in start_callback(). If * @target has not yet hit finish_callback() to clear - * utrace->reporting, we might be in the middle of a + * engine->reporting, we might be in the middle of a * callback to @engine. */ smp_mb(); - if (utrace->reporting == engine) + if (engine->reporting) ret = -EINPROGRESS; } @@ -1065,13 +1065,13 @@ int utrace_control(struct task_struct *t /* * As in utrace_set_events(), this barrier ensures * that our engine->flags changes have hit before we - * examine utrace->reporting, pairing with the barrier + * examine engine->reporting, pairing with the barrier * in start_callback(). If @target has not yet hit - * finish_callback() to clear utrace->reporting, we + * finish_callback() to clear engine->reporting, we * might be in the middle of a callback to @engine. */ smp_mb(); - if (utrace->reporting == engine) + if (engine->reporting) ret = -EINPROGRESS; } break; @@ -1228,12 +1228,12 @@ int utrace_barrier(struct task_struct *t * worry about @target making a callback. * When it has entered start_callback() but * not yet gotten to finish_callback(), we - * will see utrace->reporting == @engine. + * will see @engine->reporting == true. * When @target doesn't take the lock, it uses - * barriers to order setting utrace->reporting + * barriers to order setting engine->reporting * before it examines the engine state. */ - if (utrace->reporting != engine) + if (!engine->reporting) ret = 0; spin_unlock(&utrace->lock); if (!ret) @@ -1384,9 +1384,9 @@ static bool finish_callback(struct task_ * We don't need any barriers here because utrace_barrier() * takes utrace->lock. If we touched engine->flags above, * the lock guaranteed this change was before utrace_barrier() - * examined utrace->reporting. + * examined engine->reporting. */ - utrace->reporting = NULL; + engine->reporting = false; /* * This is a good place to make sure tracing engines don't @@ -1414,13 +1414,13 @@ static const struct utrace_engine_ops *s unsigned long want; /* - * This barrier ensures that we've set utrace->reporting before + * This barrier ensures that we've set engine->reporting before * we examine engine->flags or engine->ops. utrace_barrier() * relies on this ordering to indicate that the effect of any * utrace_control() and utrace_set_events() calls is in place - * by the time utrace->reporting can be seen to be NULL. + * by the time engine->reporting can be seen to be NULL. */ - utrace->reporting = engine; + engine->reporting = true; smp_mb(); /* @@ -1440,13 +1440,13 @@ static const struct utrace_engine_ops *s return NULL; /* - * finish_callback() reset utrace->reporting after the + * finish_callback() reset engine->reporting after the * quiesce callback. Now we set it again (as above) * before re-examining engine->flags, which could have * been changed synchronously by ->report_quiesce or * asynchronously by utrace_control() or utrace_set_events(). */ - utrace->reporting = engine; + engine->reporting = true; smp_mb(); want = engine->flags; } @@ -1459,7 +1459,7 @@ static const struct utrace_engine_ops *s return ops; } - utrace->reporting = NULL; + engine->reporting = false; return NULL; } @@ -2013,7 +2013,7 @@ int utrace_get_signal(struct task_struct /* * See start_callback() comment about this barrier. */ - utrace->reporting = engine; + engine->reporting = true; smp_mb(); /* @@ -2025,7 +2025,7 @@ int utrace_get_signal(struct task_struct ops = engine->ops; if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) { - utrace->reporting = NULL; + engine->reporting = false; continue; } From oleg at redhat.com Sat Sep 12 00:34:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 12 Sep 2009 02:34:51 +0200 Subject: Q: ptrace && ->last_siginfo Message-ID: <20090912003451.GA634@redhat.com> Now I realized I don't really understand what ->last_siginfo is. Of course, get_signal_to_deliver() case is clear. But I don't understand why ptrace_notify() setups ->last_siginfo? (I am talking about the currrent !utrace code). What for? OK, I guess .si_code = exit_code is useful, and we should be compatible anyway. Now, how we can implement this? The obvious solution is to add "struct siginfo info" into ptrace_context, but this is a bit ugly. We need the pointer in ->context, yes. But can't we avoid adding 128 bytes to ptrace_context? I mean, can't we do the following (please remember, I am ignoring signals to simplify the discussion): ptrace_setsiginfo(...) does nothing. ptrace_getsiginfo(...) { if (!context->stopped_code) // do_signal_stop() case return -EINVAL; info->si_code = context->stopped_code; info->si_signo = SIGTRAP; } ? Sure. This can break the test-case or stupid application which writes something to ->last_siginfo via ptrace_getsiginfo(), then reads the data back via ptrace_setsiginfo() and expects the "correct" results. Can we live with this? I'd really like to avoid 128 unneeded bytes in ->context. Perhaps you have other ideas? Oleg. From oleg at redhat.com Sat Sep 12 00:34:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 12 Sep 2009 02:34:54 +0200 Subject: [PATCH 29] ptrace_wake_up: fix the "compatibility bug" logic Message-ID: <20090912003454.GA642@redhat.com> I blindly copied this code from ptrace_resume() but it is wrong. task_is_stopped() can never be true, and we must not use ->sighand directly. Since the tracee should be TRACED or killed we do not check tracee->state at all. Fixes a couple of tests... --- kernel/ptrace.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) --- PU/kernel/ptrace.c~29_WAKEUP_COMPAT_BUG 2009-09-12 00:13:34.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-12 00:59:10.000000000 +0200 @@ -320,12 +320,13 @@ static void ptrace_wake_up(struct utrace struct task_struct *tracee, enum utrace_resume_action action) { + unsigned long flags; + /* preserve the compatibility bug */ - if (task_is_stopped(tracee)) { - spin_lock_irq(&tracee->sighand->siglock); - tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; - spin_unlock_irq(&tracee->sighand->siglock); - } + if (!lock_task_sighand(tracee, &flags)) + return; + tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; + unlock_task_sighand(tracee, &flags); // XXX: FIXME!!! racy. tracee->exit_code = 0; @@ -1134,10 +1135,11 @@ static int ptrace_resume(struct task_str do_notify_parent_cldstop(child, CLD_TRAPPED); read_unlock(&tasklist_lock); } else { - if (task_is_stopped(child)) { - spin_lock_irq(&child->sighand->siglock); + unsigned long flags; + + if (lock_task_sighand(child, &flags)) { child->signal->flags &= ~SIGNAL_STOP_STOPPED; - spin_unlock_irq(&child->sighand->siglock); + unlock_task_sighand(child, &flags); } /* From oleg at redhat.com Sat Sep 12 00:34:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 12 Sep 2009 02:34:56 +0200 Subject: [PATCH 30] remove the current PTRACE_EVENT_VFORK_DONE logic Message-ID: <20090912003456.GA645@redhat.com> Remove the current PTRACE_EVENT_VFORK_DONE logic, it doesn't really work anyway. I failed to finish the re-implementation today, hopefully will complete on weekend. But I have 2 questions: 1. I assume that, on every arch, we alway check TIF_NOTIFY_RESUME and TIF_SIGPENDING before TIF_SYSCALL_TRACE, right? IOW, can I assume that syscall_trace_leave() should not be called before utrace_resume() or utrace_get_signal() ? This is true (afacs) for x86, but I am not sure about other arches. 2. We have to play tricks because there is no reporting loop tracehook_report_vfork_done(). Why? I agree, UTRACE_EVENT(VFROKDONE) is meaningless because we are going to return from syscall soon and the tracer can see this event "for free". But perhaps there is another reason I missed? And, otoh, why do we have PT_TRACE_VFORK_DONE ? If it is in fact useful, then perhaps UTRACE_EVENT(VFROKDONE) is useful too? Just curious, and confused a bit. --- kernel/ptrace.c | 55 +------------------------------------------------------ 1 file changed, 1 insertion(+), 54 deletions(-) --- PU/kernel/ptrace.c~30_KILL_VFORKDONE_LOGIC 2009-09-12 00:59:10.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-12 01:04:59.000000000 +0200 @@ -230,22 +230,6 @@ static u32 ptrace_report_clone(enum utra struct ptrace_context *context = ptrace_context(engine); int event; - if ((clone_flags & CLONE_VFORK) && - (context->options & PTRACE_O_TRACEVFORKDONE)) { - /* - * Stash the child PID for a PTRACE_EVENT_VFORK_DONE report, - * even if we don't report this clone event itself. Mark - * that we vfork'd even if we don't actually stop here, so - * that we'll know to do the vfork-done report. (This - * matters when is PTRACE_O_TRACEVFORKDONE set but - * PTRACE_O_TRACEVFORK is not set.) - */ - int rc = utrace_control(parent, engine, UTRACE_REPORT); - WARN_ON(rc); - parent->ptrace_message = child->pid; - ptrace_set_stop_event(parent, PTRACE_EVENT_VFORK); - } - if (clone_flags & CLONE_UNTRACED) return UTRACE_RESUME; @@ -298,24 +282,6 @@ static u32 ptrace_report_syscall_entry(u return ptrace_report_syscall(UTRACE_SYSCALL_RUN, engine, task); } -/* - * Report a vfork-done event to precede another event report. - * There is no utrace callback associated directly with vfork-done. - * Instead, after seeing CLONE_VFORK in report_clone() we notice - * the following syscall-exit, signal, or quiesce callback and - * inject the PTRACE_EVENT_VFORK_DONE stop there. - */ -static u32 ptrace_report_vfork_done(struct task_struct *task) -{ - /* - * We got here after a vfork, when vfork-done tracing - * was enabled. - */ - ptrace_set_stop_event(task, 0); - return utrace_ptrace_event(task, PTRACE_EVENT_VFORK_DONE, - task->ptrace_message); -} - static void ptrace_wake_up(struct utrace_engine *engine, struct task_struct *tracee, enum utrace_resume_action action) @@ -370,9 +336,6 @@ static u32 ptrace_resumed(struct task_st { enum utrace_resume_action resume = ptrace_resume_action(task); - if (unlikely(ptrace_stop_event(task) == PTRACE_EVENT_VFORK)) - return UTRACE_SIGNAL_REPORT | ptrace_report_vfork_done(task); - /* * If we're stopping, or we haven't reported any signal, * then we're all done for now. @@ -480,9 +443,6 @@ static u32 ptrace_report_quiesce(u32 act if (event == 0) { task->last_siginfo = NULL; - - if (unlikely(ptrace_stop_event(task) == PTRACE_EVENT_VFORK)) - return ptrace_report_vfork_done(task); } return ptrace_resume_action(task); @@ -1090,20 +1050,7 @@ static int ptrace_resume(struct task_str break; case PTRACE_EVENT_VFORK: - /* - * For this event, @data is ignored. We did have a - * utrace stop right after, so on resuming there - * can be a normal syscall-exit stop next if needed. - * But we may need to simulate a vfork-done stop, - * so we leave the marker in place. - */ - data = 0; - event = 0; - if (context->options & PTRACE_O_TRACEVFORKDONE) { - ptrace_set_stop_event(child, - PTRACE_EVENT_VFORK); - action = UTRACE_REPORT; - } + WARN_ON(1); break; } From fatihko at nwland.ru Sat Sep 12 02:04:23 2009 From: fatihko at nwland.ru (Nicholas Field) Date: Fri, 11 Sep 2009 21:04:23 -0500 Subject: Enhance your possibilities in bed. Message-ID: <20090911210423.1010908@nwland.ru> Keep your manhood on top! http://vjikvh.ryllohwyj.com/ From Contact5 at mail.datingprotector.com Sun Sep 13 02:42:58 2009 From: Contact5 at mail.datingprotector.com (John Piepe) Date: Sun, 13 Sep 2009 09:42:58 +0700 Subject: Handbags & Shoes Message-ID: <76AAC061.555C265A@mail.datingprotector.com> Dear utrace-devel at redhat.com: Save up to 75% off on famous brand shoes. Reliable quality, best price and fast shipping! We also sell famous brand Handbags,Fashion Shoes,and other famous brands including Nike, Converse, Adidas, Puma, Kappa, Prada, Gucci, Louis Vuitton and UGGs etc. Looking forward to serving you. Contact Email: Name at Infoappender.com Other discount brand goods: Sport Clothes,T-shirts, Jeans, Hats, Wallets, Belts, Sunglasses, Wig, Wrist-watches etc. From sender at netpromouter.com Sun Sep 13 13:08:50 2009 From: sender at netpromouter.com (Meetic) Date: Sun, 13 Sep 2009 17:08:50 +0400 Subject: =?utf-8?q?Nunca_foi_t=C3=A3o_f=C3=A1cil_conhecer_pessoas_novas?= =?utf-8?q?=3F_Experimente_agora?= Message-ID: <70b47457f732ec22d2fc8e3a28754b09@www.netpromouter.com> A forma mais eficaz de conhecer novas pessoas L?der na Europa em encontros online Experimente agora... ? gr?tis! Siga este link: http://www.netpromouter.com/meetic.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexandre at unimedplanosdesaude.com.br Sun Sep 13 10:45:25 2009 From: alexandre at unimedplanosdesaude.com.br (Alexandre Unimed / Seven) Date: Sun, 13 Sep 2009 10:45:25 GMT Subject: Nova Norma da Ans foi adiada Unimed adiiou aumento confira Message-ID: Caros Amigos e Clientes caso queiram fazer ou trocar seus planos de sa?de agora ? a hora,pois a nova norma que entraria em vigor esse m?s foi adiada,sendo assim temos que correr pois como o custo das Operadoras ir? aumentar com essa nova norma ,todas as operadoras ja anunciaram aumento para o proximo m?s,acessem nosso site e solicitem sua cota??o ? muito simples preencha o formulario e receba em seu email todos os detalhes sobre o plano como valores,prazos de car?ncia e locais de atendimento. O Que Te Leva a Escolher um Plano de Saude? Plano de saude tem de ter qualidade e pre?o baixo, e ? por isso que a UNIMED ? a sua escolha. Com planos a partir de R$ 69.94*. Com atendimento nos melhores Hopitais** como:Hospital Alem?o Oswaldo Cruz, Hospital S?rio Liban?s, Pronto Socorro Infantil Sabar?, Hospital S?o Luis , Hospital Nove de Julho, Pr?-Matre Paulista e muito mais, na Unimed voc? e sua familia ter?o o melhor atendimento e a maior rede pr?pria do pais. Corra para a Unimed, e aproveite todas as nossas vantagens! Clientes Unimed contam com mais de 106 mil m?dicos**, 3.244 hospitais credenciados**, al?m de pronto-atendimentos, laborat?rios, ambul?ncias e hospitais pr?prios e credenciados para garantir qualidade na assist?ncia m?dica, hospitalar e de diagn?stico complementar oferecidos. Planos Nacionais***, Descontos em farmacias****. Acesse agora nosso site e solicite uma cota??o voc? ter? o melhor atendimento, nossa equipe ir? te ajudar a escolher um plano que realmente supere suas epectativas. Ligue agora (11) 3467-9557 estamos esperando por voc? . Seja um plano para voc?,sua familia ou para sua empresa. Na Unimed voc? encontra plano empresarial com redu??o de at? 30% nos valores apartir de 2 vidas. Acesse agora www.unimedplanosdesaude.com.br Em nosso site voc? encontra informa??es como:portabilidade, novos procedimentos obrigat?rios nos plano de saude e muito mais. Ou Ligue (11) 3467-9557 *valor referente faixa etaria de 0 a 18 anos ja com desconto promocional soliticite maiores informa??es com nossos consultores. **Dependendo do plano escolhido . ***Atendimento Nacional dependendo do plano escolhido para urgencia e emergencia. ****Solicite informa??o sobre farmacias participantes. OBS: Caso voc? n?o deseje mais receber nenhum tipo de contato nosso, clique aqui , ou envie um e-mail para remover at unimedplanosdesaude.com.br com o assunto REMOVER. www.samcilassistenciamedica.com.br -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: topo_unimed.gif Type: image/gif Size: 155282 bytes Desc: not available URL: From oleg at redhat.com Sun Sep 13 20:11:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 13 Sep 2009 22:11:10 +0200 Subject: [PATCH 31-32] finish (well, almost) ptrace_report_clone() rewrite Message-ID: <20090913201110.GA16209@redhat.com> PTRACE_EVENT_VFORK_DONE kills me. I spent the whole weekend, but still need more debugging/fixes. The changelog includes the test-case I wrote and says it works. But! if I run the several instances in parallel, then after 3-5 minutes it fails: TRACEVFORKDONE is not reported. And of course, if I add printk's the problem goes away. Still investigating. Oleg. From oleg at redhat.com Sun Sep 13 20:11:13 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 13 Sep 2009 22:11:13 +0200 Subject: [PATCH 31] ptrace_report_clone: rework the stop/resume logic Message-ID: <20090913201113.GA16217@redhat.com> TODO: 1. CLEANUP !!!! 2. CLONE_UNTRACE check is wrong 3. child->pid is wrong, we must use tracer's namespace Note: Ugly, but we have to add context->o_did_clone_vfork bolean, it is true if the last do_fork() had CLONE_VFORK. We can't figure out whether we need PTRACE_O_TRACEVFORKDONE at ptrace_report_clone() time, the tracer can change options after we report PTRACE_EVENT_VFORK. Passes this test: #include #include #include #include #include #include #include #include #define WEVENT(s) ((s & 0xFF0000) >> 16) static unsigned long __step(int line, int pid, int o, int e) { int stat, cont = PTRACE_CONT; unsigned long msg; if (o == PTRACE_SYSCALL) { cont = o; } else if (o) { assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, o)); } assert(0 == ptrace(cont, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); assert(WIFSTOPPED(stat)); assert(WSTOPSIG(stat) == SIGTRAP); assert(WEVENT(stat) == e); assert(0 == ptrace(PTRACE_GETEVENTMSG, pid, 0, &msg)); return msg; } #define step(pid, o, e) __step(__LINE__, pid, o, e) #define T_FORK_A 0x01 #define T_FORK_Z 0x02 #define T_SYSCALL 0x04 #define T_SIGNAL 0x08 #define T_ALL (T_FORK_A | T_FORK_Z | T_SYSCALL | T_SIGNAL) static void p_todo(int todo) { printf("todo: "); #define P(n) if (todo & n) printf(#n " ") P(T_FORK_A); P(T_FORK_Z); P(T_SYSCALL); P(T_SIGNAL); #undef P if (todo & ~T_ALL) printf("ERR!!!"); printf("\n"); } static void tst(int todo) { int pid, cpid=-1, stat; long msg; p_todo(todo); pid = fork(); if (!pid) { int vp; if (!(todo & T_SIGNAL)) signal(SIGCHLD, SIG_IGN); assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); vp = vfork(); exit(0x43); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); if (todo & T_SYSCALL) { msg = step(pid, PTRACE_SYSCALL, 0); assert(msg == 0); } if (todo & T_FORK_A) { cpid = step(pid, PTRACE_O_TRACEVFORK, PTRACE_EVENT_VFORK); assert(waitpid(cpid, &stat, __WALL) == cpid); assert(WIFSTOPPED(stat)); assert(WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_CONT, cpid, 0, 0)); assert(waitpid(cpid, &stat, __WALL) == cpid); assert(WIFEXITED(stat)); } if (todo & T_FORK_Z) { msg = step(pid, PTRACE_O_TRACEVFORKDONE, PTRACE_EVENT_VFORK_DONE); if (todo & T_FORK_A) assert(msg == cpid); } if (todo & T_SIGNAL) { assert(0 == ptrace(PTRACE_CONT, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); if (!(todo & T_FORK_A) && stat == 0x4300) goto parent_exited_first; assert(WIFSTOPPED(stat)); assert(WSTOPSIG(stat) == SIGCHLD); } if (todo & T_SYSCALL) { msg = step(pid, PTRACE_SYSCALL, 0); if (todo & T_FORK_A) assert(msg == cpid); } assert(0 == ptrace(PTRACE_CONT, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); assert(WIFEXITED(stat)); parent_exited_first: assert(waitpid(-1, &stat, __WALL) == -1); assert(errno == ECHILD); } int main(int argc, char* argv[]) { int todo; if (argc > 1) { todo = atoi(argv[1]); tst(todo); } else { int todo; for (todo = 0; todo <= T_ALL; ++todo) tst(todo); } return 0; } --- kernel/ptrace.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~31_TRACEVFORKDONE 2009-09-12 01:04:59.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-13 21:22:24.000000000 +0200 @@ -32,6 +32,8 @@ struct ptrace_context { int stopped_code; resume_stopped_t resume_stopped; + + bool o_did_clone_vfork; // XXX: move into ->options }; static inline struct ptrace_context * @@ -56,6 +58,8 @@ void __ptrace_link(struct task_struct *c static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */ static int ptrace_attach_task(struct task_struct *tracee, int options); static void ptrace_abort_attach(struct task_struct *tracee); +static void ptrace_wake_up(struct utrace_engine *engine, + struct task_struct *tracee, enum utrace_resume_action action); static void ptrace_detach_task(struct task_struct *child, int sig) { @@ -221,6 +225,35 @@ static void ptrace_clone_attach(struct t set_tsk_thread_flag(child, TIF_SIGPENDING); } +static void ptrace_resume_vfork_done(struct utrace_engine *engine, + struct task_struct *tracee, long data) +{ + ptrace_wake_up(engine, tracee, UTRACE_RESUME); +} + +static bool ck_o_tracevforkdone(struct utrace_engine *engine, + struct task_struct *tracee) +{ + struct ptrace_context *context = ptrace_context(engine); + + if (!(context->o_did_clone_vfork && + (context->options & PTRACE_O_TRACEVFORKDONE))) + return false; + + context->resume_stopped = ptrace_resume_vfork_done; + context->stopped_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP; + + utrace_control(tracee, engine, UTRACE_REPORT); + return true; +} + +static void ptrace_resume_clone(struct utrace_engine *engine, + struct task_struct *tracee, long data) +{ + ck_o_tracevforkdone(engine, tracee); + ptrace_wake_up(engine, tracee, UTRACE_RESUME); +} + static u32 ptrace_report_clone(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *parent, @@ -230,11 +263,16 @@ static u32 ptrace_report_clone(enum utra struct ptrace_context *context = ptrace_context(engine); int event; + WARN_ON(context->resume_stopped); + WARN_ON(context->stopped_code); + if (clone_flags & CLONE_UNTRACED) return UTRACE_RESUME; event = 0; + context->o_did_clone_vfork = false; if (clone_flags & CLONE_VFORK) { + context->o_did_clone_vfork = true; if (context->options & PTRACE_O_TRACEVFORK) event = PTRACE_EVENT_VFORK; } else if ((clone_flags & CSIGNAL) != SIGCHLD) { @@ -251,8 +289,16 @@ static u32 ptrace_report_clone(enum utra if (event || (clone_flags & CLONE_PTRACE)) ptrace_clone_attach(parent, child, context->options); - if (event) - return utrace_ptrace_event(parent, event, child->pid); + // XXX: child->pid is wrong! use tracer's pid_ns + if (event) { + parent->ptrace_message = child->pid; + context->resume_stopped = ptrace_resume_clone; + context->stopped_code = (event << 8) | SIGTRAP; + + return UTRACE_STOP; + } else if (ck_o_tracevforkdone(engine, parent)) { + parent->ptrace_message = child->pid; + } return UTRACE_RESUME; } From oleg at redhat.com Sun Sep 13 20:11:16 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 13 Sep 2009 22:11:16 +0200 Subject: [PATCH 32] ptrace_report_syscall_exit: do not WARN() if killed Message-ID: <20090913201116.GA16220@redhat.com> ptrace_report_syscall_exit() can be entered when the tracee is killed, in that case resume_stopped/stopped_code can be set. --- kernel/ptrace.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~32_REPORT_SYSCALL_EXIT_CK_KILLED 2009-09-13 21:22:24.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-13 21:46:39.000000000 +0200 @@ -367,8 +367,11 @@ static u32 ptrace_report_syscall_exit(en { struct ptrace_context *context = ptrace_context(engine); - WARN_ON(context->resume_stopped); - WARN_ON(context->stopped_code); + // XXX: temporary debugging check... + if (!fatal_signal_pending(task)) { + WARN_ON(context->resume_stopped); + WARN_ON(context->stopped_code); + } context->resume_stopped = ptrace_resume_syscall; context->stopped_code = (context->options & PTRACE_O_TRACESYSGOOD) ? From oleg at redhat.com Mon Sep 14 00:39:19 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 14 Sep 2009 02:39:19 +0200 Subject: do_notify_resume && syscall_trace_leave (Was: [PATCH 30] remove the current PTRACE_EVENT_VFORK_DONE logic) In-Reply-To: <20090912003456.GA645@redhat.com> References: <20090912003456.GA645@redhat.com> Message-ID: <20090914003919.GA6990@redhat.com> On 09/12, Oleg Nesterov wrote: > > 1. I assume that, on every arch, we alway check TIF_NOTIFY_RESUME > and TIF_SIGPENDING before TIF_SYSCALL_TRACE, right? > > IOW, can I assume that syscall_trace_leave() should not be called > before utrace_resume() or utrace_get_signal() ? > > This is true (afacs) for x86, but I am not sure about other > arches. Damn! I am stupid. No, this is NOT true even on x86. I greatly misread entry_64.S:int_very_careful, _TIF_WORK_SYSCALL_EXIT does NOT include _TIF_DO_NOTIFY_MASK. OK, makes sense, we are not going to return to the user-mode yet... Oh. So we really need the stack of stop events, and I have to change my plan... Stupid me. Oleg. From oleg at redhat.com Mon Sep 14 06:06:33 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 14 Sep 2009 08:06:33 +0200 Subject: [PATCH 33] implement stacked stop events Message-ID: <20090914060633.GA8446@redhat.com> As I said, I greatly misread asm code, ->report_syscall_exit() can be called without utrace_resume/utrace_get_signal. We need the stack of stop events. Not the stack in fact, array. Incomplete. The code needs cleanup/refactoring. In particular, ptrace_report_clone() case is still not right. We can't check PTRACE_O_TRACEVFORKDONE in do_fork() path, it can be set later. But it passes clone/vfork tests. Btw, compared to vanilla kernel, the following tests fail: FAIL: attach-wait-on-stopped FAIL: step-into-handler FAIL: step-through-sigret FAIL: detach-stopped FAIL: detach-parting-signal And note that "detach-stopped" should not succeed in fact, it needs the "detach always wakes up the child" logic which was removed. --- kernel/ptrace.c | 168 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 109 insertions(+), 59 deletions(-) --- PU/kernel/ptrace.c~33_EV_ARRAY 2009-09-14 04:17:07.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-14 07:43:43.000000000 +0200 @@ -24,18 +24,53 @@ #include #include -typedef void (*resume_stopped_t)(struct utrace_engine *, +typedef void (*resume_func_t)(struct utrace_engine *, struct task_struct*, long); +struct ptrace_event { + int ev_code; + unsigned long ev_message; + resume_func_t ev_resume; +}; + struct ptrace_context { int options; - int stopped_code; - resume_stopped_t resume_stopped; - - bool o_did_clone_vfork; // XXX: move into ->options + struct ptrace_event ev_array[2]; + unsigned int ev_first, ev_last; }; +static inline bool ev_empty(struct ptrace_context *context) +{ + return context->ev_first == context->ev_last; +} + +static inline struct ptrace_event *__ev_at(struct ptrace_context *context, + unsigned int idx) +{ + return context->ev_array + (idx % ARRAY_SIZE(context->ev_array)); +} + +static inline struct ptrace_event *ev_current(struct ptrace_context *context) +{ + WARN_ON(ev_empty(context)); + return __ev_at(context, context->ev_first); +} + +static inline struct ptrace_event *ev_pop(struct ptrace_context *context) +{ + WARN_ON(ev_empty(context)); + return __ev_at(context, context->ev_first++); +} + +static inline struct ptrace_event *ev_push(struct ptrace_context *context) +{ + struct ptrace_event *ev = __ev_at(context, context->ev_last++); + WARN_ON(context->ev_last - context->ev_first > ARRAY_SIZE(context->ev_array)); + memset(ev, 0, sizeof(*ev)); + return ev; +} + static inline struct ptrace_context * ptrace_context(struct utrace_engine *engine) { @@ -60,6 +95,8 @@ static int ptrace_attach_task(struct tas static void ptrace_abort_attach(struct task_struct *tracee); static void ptrace_wake_up(struct utrace_engine *engine, struct task_struct *tracee, enum utrace_resume_action action); +static void do_ptrace_notify_stop(struct ptrace_context *context, + struct task_struct *tracee); static void ptrace_detach_task(struct task_struct *child, int sig) { @@ -231,26 +268,9 @@ static void ptrace_resume_vfork_done(str ptrace_wake_up(engine, tracee, UTRACE_RESUME); } -static bool ck_o_tracevforkdone(struct utrace_engine *engine, - struct task_struct *tracee) -{ - struct ptrace_context *context = ptrace_context(engine); - - if (!(context->o_did_clone_vfork && - (context->options & PTRACE_O_TRACEVFORKDONE))) - return false; - - context->resume_stopped = ptrace_resume_vfork_done; - context->stopped_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP; - - utrace_control(tracee, engine, UTRACE_REPORT); - return true; -} - static void ptrace_resume_clone(struct utrace_engine *engine, struct task_struct *tracee, long data) { - ck_o_tracevforkdone(engine, tracee); ptrace_wake_up(engine, tracee, UTRACE_RESUME); } @@ -261,18 +281,16 @@ static u32 ptrace_report_clone(enum utra struct task_struct *child) { struct ptrace_context *context = ptrace_context(engine); - int event; + int event, ret = UTRACE_RESUME; - WARN_ON(context->resume_stopped); - WARN_ON(context->stopped_code); + WARN_ON(!ev_empty(context)); + // XXX: WRONG!!! if (clone_flags & CLONE_UNTRACED) - return UTRACE_RESUME; + return ret; event = 0; - context->o_did_clone_vfork = false; if (clone_flags & CLONE_VFORK) { - context->o_did_clone_vfork = true; if (context->options & PTRACE_O_TRACEVFORK) event = PTRACE_EVENT_VFORK; } else if ((clone_flags & CSIGNAL) != SIGCHLD) { @@ -291,16 +309,27 @@ static u32 ptrace_report_clone(enum utra // XXX: child->pid is wrong! use tracer's pid_ns if (event) { - parent->ptrace_message = child->pid; - context->resume_stopped = ptrace_resume_clone; - context->stopped_code = (event << 8) | SIGTRAP; + struct ptrace_event *ev = ev_push(context); - return UTRACE_STOP; - } else if (ck_o_tracevforkdone(engine, parent)) { - parent->ptrace_message = child->pid; + ev->ev_message = child->pid; + ev->ev_resume = ptrace_resume_clone; + ev->ev_code = (event << 8) | SIGTRAP; + + ret = UTRACE_STOP; } - return UTRACE_RESUME; + if ((clone_flags & CLONE_VFORK) && + (context->options & PTRACE_O_TRACEVFORKDONE)) { + struct ptrace_event *ev = ev_push(context); + + ev->ev_message = child->pid; + ev->ev_resume = ptrace_resume_vfork_done; + ev->ev_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP; + + ret = UTRACE_STOP; + } + + return ret; } static u32 ptrace_report_syscall(u32 action, struct utrace_engine *engine, @@ -328,12 +357,19 @@ static u32 ptrace_report_syscall_entry(u return ptrace_report_syscall(UTRACE_SYSCALL_RUN, engine, task); } +// XXX: move this all into ptrace_resume() static void ptrace_wake_up(struct utrace_engine *engine, struct task_struct *tracee, enum utrace_resume_action action) { + struct ptrace_context *context = ptrace_context(engine); unsigned long flags; + if (!ev_empty(context)) { + do_ptrace_notify_stop(context, tracee); + return; + } + /* preserve the compatibility bug */ if (!lock_task_sighand(tracee, &flags)) return; @@ -366,16 +402,12 @@ static u32 ptrace_report_syscall_exit(en struct pt_regs *regs) { struct ptrace_context *context = ptrace_context(engine); + struct ptrace_event *ev; - // XXX: temporary debugging check... - if (!fatal_signal_pending(task)) { - WARN_ON(context->resume_stopped); - WARN_ON(context->stopped_code); - } - - context->resume_stopped = ptrace_resume_syscall; - context->stopped_code = (context->options & PTRACE_O_TRACESYSGOOD) ? - (SIGTRAP | 0x80) : SIGTRAP; + ev = ev_push(context); + ev->ev_resume = ptrace_resume_syscall; + ev->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? + (SIGTRAP | 0x80) : SIGTRAP; return UTRACE_STOP; } @@ -440,7 +472,8 @@ static u32 ptrace_report_signal(u32 acti { struct ptrace_context *context = ptrace_context(engine); - if (context->stopped_code) { + if (!ev_empty(context)) { + WARN_ON(!ev_current(context)->ev_code && !fatal_signal_pending(task)); action = utrace_signal_action(action); WARN_ON(action != UTRACE_SIGNAL_REPORT); return action | UTRACE_STOP; @@ -487,8 +520,10 @@ static u32 ptrace_report_quiesce(u32 act { struct ptrace_context *context = ptrace_context(engine); - if (context->stopped_code) + if (!ev_empty(context)) { + WARN_ON(!ev_current(context)->ev_code && !fatal_signal_pending(task)); return UTRACE_STOP; + } if (event == 0) { task->last_siginfo = NULL; @@ -954,6 +989,24 @@ static int ptrace_setsiginfo(struct task #define is_sysemu_singlestep(request) 0 #endif +static void do_ptrace_notify_stop(struct ptrace_context *context, + struct task_struct *tracee) +{ + struct ptrace_event *ev = ev_current(context); + + if (ev->ev_message) + tracee->ptrace_message = ev->ev_message; + tracee->exit_code = ev->ev_code; + + // XXX: for debug only + WARN_ON(ev->ev_code == 0); + ev->ev_code = 0; + + read_lock(&tasklist_lock); + do_notify_parent_cldstop(tracee, CLD_TRAPPED); + read_unlock(&tasklist_lock); +} + void ptrace_notify_stop(struct task_struct *tracee) { struct utrace_engine *engine; @@ -968,16 +1021,11 @@ void ptrace_notify_stop(struct task_stru } context = ptrace_context(engine); - if (context->stopped_code) { - tracee->exit_code = context->stopped_code; - context->stopped_code = 0; - - read_lock(&tasklist_lock); - do_notify_parent_cldstop(tracee, CLD_TRAPPED); - read_unlock(&tasklist_lock); + if (!ev_empty(context)) { + do_ptrace_notify_stop(context, tracee); + return; } - // XXX: will die soon if (ptrace_resume_action(tracee) == UTRACE_STOP) { read_lock(&tasklist_lock); do_notify_parent_cldstop(tracee, CLD_TRAPPED); @@ -1034,11 +1082,13 @@ static int ptrace_resume(struct task_str if (!ret) { int event; - if (context->resume_stopped) { - resume_stopped_t resume = context->resume_stopped; - context->resume_stopped = NULL; - WARN_ON(context->stopped_code); - resume(engine, child, data); + if (!ev_empty(context)) { + struct ptrace_event *ev = ev_pop(context); + + WARN_ON(ev->ev_code); // XXX: debug + ev->ev_resume(engine, child, data); + ev->ev_resume = NULL; // XXX: debug + utrace_engine_put(engine); return 0; } From roland at redhat.com Mon Sep 14 07:58:56 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 14 Sep 2009 00:58:56 -0700 (PDT) Subject: [PATCH] move ->reporting from struct utrace to utrace_engine In-Reply-To: Oleg Nesterov's message of Saturday, 12 September 2009 02:34:25 +0200 <20090912003425.GA611@redhat.com> References: <20090912003425.GA611@redhat.com> Message-ID: <20090914075856.3AF347414@magilla.sf.frob.com> > But can't we move ->reporting from utrace to engine? This saves a word > in task_struct. Yes, this adds the same word to engine, but we should > optimize the common untraced case. That will be optimized properly when we move struct utrace out of task_struct. Inflating the size of struct utrace_engine does not make any sense to me. Thanks, Roland From roland at redhat.com Mon Sep 14 08:15:47 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 14 Sep 2009 01:15:47 -0700 (PDT) Subject: [PATCH 30] remove the current PTRACE_EVENT_VFORK_DONE logic In-Reply-To: Oleg Nesterov's message of Saturday, 12 September 2009 02:34:56 +0200 <20090912003456.GA645@redhat.com> References: <20090912003456.GA645@redhat.com> Message-ID: <20090914081547.E01F873F8@magilla.sf.frob.com> > 1. I assume that, on every arch, we alway check TIF_NOTIFY_RESUME > and TIF_SIGPENDING before TIF_SYSCALL_TRACE, right? No, these are only checked when you would otherwise return to user mode. > IOW, can I assume that syscall_trace_leave() should not be called > before utrace_resume() or utrace_get_signal() ? No, if TIF_SYSCALL_TRACE is still set when sys_foo returns, then tracehook_report_syscall_exit will always be called first. Only after that do you get to "would otherwise return to user mode" state. > 2. We have to play tricks because there is no reporting loop > tracehook_report_vfork_done(). > > Why? I agree, UTRACE_EVENT(VFROKDONE) is meaningless because > we are going to return from syscall soon and the tracer can > see this event "for free". Right. It also seems more useful to me if the place you catch in the parent is at/after the syscall-exit tracing point, where the parent's return value register has the child's PID. > But perhaps there is another reason I missed? And, otoh, > why do we have PT_TRACE_VFORK_DONE ? If it is in fact useful, > then perhaps UTRACE_EVENT(VFROKDONE) is useful too? Personally I don't think PTRACE_O_TRACEVFORKDONE is particularly useful. That is, you could always just catch PTRACE_EVENT_VFORK in the parent and then use PTRACE_SYSCALL instead of PTRACE_CONT, and you'd know that what you catch next in the parent is the exit from the vfork/clone syscall. But it's part of the legacy ptrace ABI. I've thought that in the long run it might be nice to change the wait the vfork block works such that we could let a blocked vfork parent be considered "stopped enough" for tracing (and perhaps also so it could be SIGKILL'd without waiting for the child to die/exec). But that is its own whole can of worms. As well as the implementation, there is the whole hairy subject of what you want to be doing with the parent during the period of strange memory sharing. That's a thought for another day. Thanks, Roland From oleg at redhat.com Mon Sep 14 08:22:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 14 Sep 2009 10:22:00 +0200 Subject: [PATCH] move ->reporting from struct utrace to utrace_engine In-Reply-To: <20090914075856.3AF347414@magilla.sf.frob.com> References: <20090912003425.GA611@redhat.com> <20090914075856.3AF347414@magilla.sf.frob.com> Message-ID: <20090914082200.GA21577@redhat.com> On 09/14, Roland McGrath wrote: > > > But can't we move ->reporting from utrace to engine? This saves a word > > in task_struct. Yes, this adds the same word to engine, but we should > > optimize the common untraced case. > > That will be optimized properly when we move struct utrace out of task_struct. OK, then please ignore this patch. But, > Inflating the size of struct utrace_engine does not make any sense to me. The size of task_struct is more important. The traced task is unlikely case. So, until we move utrace out of task_struct this saves the memory. Oleg. From roland at redhat.com Mon Sep 14 08:27:37 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 14 Sep 2009 01:27:37 -0700 (PDT) Subject: [PATCH 31-32] finish (well, almost) ptrace_report_clone() rewrite In-Reply-To: Oleg Nesterov's message of Sunday, 13 September 2009 22:11:10 +0200 <20090913201110.GA16209@redhat.com> References: <20090913201110.GA16209@redhat.com> Message-ID: <20090914082737.C2FD473F8@magilla.sf.frob.com> > PTRACE_EVENT_VFORK_DONE kills me. I spent the whole weekend, but > still need more debugging/fixes. This is a somewhat obscure feature, and we still have quite a mess overall. Really I think it would be fine (and perhaps even wisest in overall time allocation) if you just punt this corner until the rest of the stuff is cleaned up more. Thanks, Roland From roland at redhat.com Mon Sep 14 08:32:51 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 14 Sep 2009 01:32:51 -0700 (PDT) Subject: [PATCH 33] implement stacked stop events In-Reply-To: Oleg Nesterov's message of Monday, 14 September 2009 08:06:33 +0200 <20090914060633.GA8446@redhat.com> References: <20090914060633.GA8446@redhat.com> Message-ID: <20090914083251.BB2E073F8@magilla.sf.frob.com> This code has no comments whatsoever. I know you intend much more cleanup to come anyway, but this can make it hard even to review the code and give advice on the directions you are taking. I don't understand why you need the hairy ev_array logic at all. There isn't really any extra information you need to record, is there? Each "extra" event follows exactly one particular previous event, so it's just a very simple state machine. Thanks, Roland From roland at redhat.com Mon Sep 14 09:05:10 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 14 Sep 2009 02:05:10 -0700 (PDT) Subject: Q: ptrace && ->last_siginfo In-Reply-To: Oleg Nesterov's message of Saturday, 12 September 2009 02:34:51 +0200 <20090912003451.GA634@redhat.com> References: <20090912003451.GA634@redhat.com> Message-ID: <20090914090510.CCD0D7414@magilla.sf.frob.com> > What for? OK, I guess .si_code = exit_code is useful, and we should > be compatible anyway. This comment above ptrace_stop: * We always set current->last_siginfo while stopped here. * That makes it a way to test a stopped process for * being ptrace-stopped vs being job-control-stopped. dates from the 2004 rewrite (original introduction of TASK_TRACED) that made this ABI change. I'd have to look up the mailing list archives of the time to be sure, but my dim recollection is that this was the preference of the GDB folks at the time. Since then I have probably advised people more than once that PTRACE_GETSIGINFO->EINVAL is a check for job control stops. > Now, how we can implement this? The obvious solution is to add > "struct siginfo info" into ptrace_context, but this is a bit ugly. > We need the pointer in ->context, yes. But can't we avoid adding > 128 bytes to ptrace_context? As you noted, in the non-signal cases it doesn't actually store any extra useful information about the event. So it's not always needed at event time. > Sure. This can break the test-case or stupid application which writes > something to ->last_siginfo via ptrace_getsiginfo(), then reads the data > back via ptrace_setsiginfo() and expects the "correct" results. Hmm. I don't think we care if reading it back with PTRACE_GETSIGINFO is the only way to notice. It looks quite clear in the vanilla kernel that nothing else could be affected, since it's a siginfo_t local in ptrace_notify that is just abandoned. > Can we live with this? At the moment it seems like we can. We should keep the subject in mind though. > I'd really like to avoid 128 unneeded bytes in ->context. Perhaps you > have other ideas? Worst case we could kalloc something in the rare case of the PTRACE_SETSIGINFO call that had new information to store. For now we could punt it and do a WARN_ON_ONCE for the case of a PTRACE_SETSIGINFO call in that situation (or perhaps only for one that sets it to other than what the default dummy read would yield). Thanks, Roland From oleg at redhat.com Mon Sep 14 10:18:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 14 Sep 2009 12:18:36 +0200 Subject: [PATCH 33] implement stacked stop events In-Reply-To: <20090914083251.BB2E073F8@magilla.sf.frob.com> References: <20090914060633.GA8446@redhat.com> <20090914083251.BB2E073F8@magilla.sf.frob.com> Message-ID: <20090914101836.GA26416@redhat.com> On 09/14, Roland McGrath wrote: > > This code has no comments whatsoever. I know you intend much more cleanup > to come anyway, but this can make it hard even to review the code and give > advice on the directions you are taking. Yes. Will try to fix later. > I don't understand why you need the hairy ev_array logic at all. Basically, we have ev_push() and ev_pop(), that is all. Roughly speaking, if we are going to return UTRACE_STOP we call ev_push() to record the state. ptrace_resume() does ev_pop() and wakes up if there are no a stop event. > There isn't really any extra information you need to record, is there? We need to record the values for task->exit_code and task->ptrace_message at least. _Perhaps_, we also need to record the bit from context->options, I am not sure. > Each "extra" event follows exactly one particular previous event, so > it's just a very simple state machine. Yes, this is mostly simple. But probably sometimes we need some fixups when chane the state. Again, I am not sure, dind't sleep today. Oleg. From cisse at cisse2009online.org Tue Sep 8 11:06:52 2009 From: cisse at cisse2009online.org (CISSE 2009) Date: Tue, 08 Sep 2009 07:06:52 -0400 Subject: Call for Papers: The 5th CISSE International Conference Message-ID: <03a3b3a7ec82f26caa8c110d5ba473e3@topspotlistings.com> Dear Colleagues, If you received this email in error, please forward it to the appropriate department at your institution. If you wish to unsubscribe please follow the unsubscribe link at bottom of the email. Please do not reply to this message. If you need to contact us please email us at info at cisse2009online.org ********************************************************************** * The Fifth International Joint Conferences on Computer, * * Information, and Systems Sciences, and Engineering (CISSE 2009) * * * * http://topspotlistings.com/IEM/link.php?M=157815&N=9&L=1&F=T * * * ********************************************************************** December 4-12, 2009 Sponsored by the University of Bridgeport Technically co-sponsored by the IEEE Computer Society, Communications Society and Education Society (Connecticut Section) --------------------------------------------------------------------- CONFERENCE OVERVIEW --------------------------------------------------------------------- CISSE 2009 provides a virtual forum for presentation and discussion of the state-of the-art research on computers, information and systems sciences and engineering. CISSE 2009 is the fifth conference of the CISSE series of e-conferences. CISSE is the World's first Engineering/Computing and Systems Research E-Conference. CISSE 2005 was the first high-caliber Research Conference in the world to be completely conducted online in real-time via the internet. CISSE 2005 received 255 research paper submissions and the final program included 140 accepted papers, from more than 45 countries. CISSE 2006 received 691 research paper submissions and the final program included 390 accepted papers, from more than 70 countries. CISSE 2007 received 750 research paper submissions and the final program included 406 accepted papers. A total of 948 paper submissions were received for CISSE 2008 and the final program included 382 accepted papers, from more than 80 countries. The virtual conference will be conducted through the Internet using web-conferencing tools, made available by the conference. Authors will be presenting their PowerPoint, audio or video presentations using web-conferencing tools without the need for travel. Conference sessions will be broadcast to all the conference participants, where session participants can interact with the presenter during the presentation and/or during the Q&A slot that follows the presentation. This international conference will be held entirely on-line. The accepted and presented papers will be made available and sent to the authors after the conference both on a DVD (including all papers, PowerPoint presentations and audio presentations) and as a book publication. Springer, the official publisher for CISSE, published the 2005 proceedings in 2 books and the CISSE 2006, CISSE 2007 and CISSE 2008 proceedings in four books each. Conference participants - authors, presenters and attendees - only need an internet connection and sound available on their computers in order to be able to contribute and participate in this international ground-breaking conference. The on-line structure of this high-quality event will allow academic professionals and industry participants to contribute their work and attend world-class technical presentations based on rigorously refereed submissions, live, without the need for investing significant travel funds or time out of the office. The concept and format of CISSE is ground-breaking. The PowerPoint presentations, final paper manuscripts and time schedule for live presentations over the web had been available for weeks prior to the start of the conference for all registrants, so that the participants can choose the presentations they want to attend and think about questions that they might want to ask. The live audio presentations were also recorded and are part of the permanent CISSE on-line archive - accessible to all registrants - which also includes all the papers, PowerPoint and audio presentations. Potential non-author conference attendees who cannot make the on-line conference dates are encouraged to register, as the entire joint conferences will be archived for future viewing. The CISSE conference audio room provides superb audio even over low speed internet connections, the ability to display PowerPoint presentations, and cross-platform compatibility (the conferencing software runs on Windows, Mac, and any other operating system that supports Java). In addition, the conferencing system allowed for an unlimited number of participants, which in turn granted us the opportunity to allow all CISSE participants to attend all presentations, as opposed to limiting the number of available seats for each session. Prospective authors are invited to submit full papers electronically in Microsoft Word or Adobe PDF format through the website of the conference at: http://topspotlistings.com/IEM/link.php?M=157815&N=9&L=1&F=T Accepted papers must be presented in the virtual conference by one of the authors. To submit your paper, please visit http://topspotlistings.com/IEM/link.php?M=157815&N=9&L=1&F=T CISSE 2009 is composed of the following four conferences: International Conference on Systems, Computing Sciences and Software Engineering (SCSS 09) Topics: Grid Computing, Internet-based Computing Models, Resource Discovery, Programming Models and tools, e-Science and Virtual Instrumentation, Biometric Authentication, Computers for People of Special Needs, Human Computer Interaction, Information and Knowledge Engineering, Algorithms, Parallel and Distributed processing, Modeling and Simulation, Services and Applications, Embedded Systems and Applications, Databases, Programming Languages, Signal Processing Theory and Methods, Signal Processing for Communication, Signal Processing Architectures and Implementation, Information Processing, Geographical Information Systems,Object Based Software Engineering, Parallel and Distributed Computing, Real Time Systems, Multiprocessing, File Systems and I/O, Kernel and OS Structures. International Conference on Telecommunications and Networking (TeNe 09) Topics: Optical Networks and Switching, Computer Networks, Network architectures and Equipment, Access Technologies, Telecommunication Technology, Coding and Modulation technique, Modeling and Simulation, Spread Spectrum and CDMA Systems, OFDM technology, Space-time Coding, Ultra Wideband Communications, Medium Access Control, Spread Spectrum, Wireless LAN: IEEE 802.11, HIPERLAN, Bluetooth, Cellular Wireless Networks, Cordless Systems and Wireless Local Loop, Mobile Network Layer, Mobile Transport Layer, Support for Mobility, Conventional Encryption and Message Confidentiality, Block Ciphers Design Principles, Block Ciphers Modes of Operation, Public-Key Cryptography and Message Authentication, Authentication Application, Stenography, Electronic Mail Security, Web Security, IP Security, Firewalls, Computer Forensics. International Conference on Engineering Education, Instructional Technology, Assessment, and E-learning (EIAE 09) Topics: Instructional Design, Accreditation, Curriculum Design, Educational Tools, 2-2-2 Platforms, Teaching Capstone Design, Teaching Design at the Lower Levels, Design and Development of e-Learning tools, Assessment Methods in Engineering, Development and Implementation of E-learning tools, Ethics in Education, Economical and Social Impacts of E-learning. International Conference on Industrial Electronics, Technology & Automation (IETA 09) Topics: Advanced and Distributed Control Systems, Intelligent Control Systems (NN, FL, GA, .etc), Expert Systems, Man Machine Interaction, Data Fusion, Factory Automation, Robotics, Motion Control, Machine Vision, MEMS Sensors and Actuators, Sensors Fusion, Power Electronics, High Frequency Converters, Motors and Drives, Power Converters, Power Devices and Components, Electric Vehicles and Intelligent Transportation, Process Automation, Factory Communication, Manufacturing Information System Advances in Manufacturing Systems, Industrial Applications of Multi Media, Intelligent Systems Instrumentation, Industrial Instrumentation, Modeling and Simulation, Signal Processing, Image and Data Processing, VR and Parallel systems. Paper Submission ================= Prospective authors are invited to submit full papers electronically in Microsoft Word or Adobe PDF format through the website of the conference at http://topspotlistings.com/IEM/link.php?M=157815&N=9&L=1&F=T Accepted papers must be presented in the virtual conference by one of the authors. To submit your paper, please visit http://topspotlistings.com/IEM/link.php?M=157815&N=9&L=1&F=T Paper submission Deadline: October 12th, 2009 Notification of Acceptance: November 13th, 2009 Final Manuscript and Registration: November 26th, 2009 ------------------------------------------------------------------------ S. Patel Technical Support, CISSE 2009 University of Bridgeport 221 University Avenue info at cisse2009online.org Bridgeport, CT 06604, U.S.A. http://topspotlistings.com/IEM/link.php?M=157815&N=9&L=1&F=T ------------------------------------------------------------------------ TO UNSUBSCRIBE FROM OUR LIST AND STOP RECEVING EMAILS FROM CISSE PERMANENTLY please visit http://topspotlistings.com/IEM/link.php?M=157815&N=9&L=2&F=T. We honor all unsubscribe requests. -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Tue Sep 15 18:48:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 15 Sep 2009 20:48:49 +0200 Subject: [PATCH 34-40] stop/resume cleanups, exec/syscall conversions Message-ID: <20090915184849.GA2369@redhat.com> I didn't have time to finish ptrace_report_clone(), but I think this will be simple now... Oleg. From oleg at redhat.com Tue Sep 15 18:48:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 15 Sep 2009 20:48:51 +0200 Subject: [PATCH 34] cleanup/simplify stop/resume mess Message-ID: <20090915184851.GA2378@redhat.com> The code still needs comments. I'll try to explain how the code should work at least here. struct ptrace_event { int ev_code; unsigned long ev_message; resume_func_t ev_resume; }; This represents the state of the tracee when it stops, ->ev_code == tracee->exit_code ->ev_message == tracee->ptrace_message ->ev_resume == non-NULL if we need some special action on resume, for example syscall entry/exit do send_sig() struct ptrace_context has a simple FIFO struct ptrace_event ev_array[2]; and two simple helpers: ev_push() - for tracee, add the new event ev_pop() - for tracer, dequeue the first event For example, lets see what happens when the tracee reports syscall_exit. ptrace_report_syscall_exit() simply does ev_push() and that is all. No need to worry in case this event is stacked. Say, we may have PTRACE_EVENT_EXEC which should be reported first. When the tracee actually stops, ptrace_notify_stop() looks at the first ptrace_event, setups ->exit_code and notifies the tracer. ptrace_resume() does ev_push(), calls ->ev_resume() if it is !NULL. If we have more events, it calls ptrace_notify_stop() to trick ptrace into thinking the tracee stops again, otherwise it wakes up the tracee. I think this is more readable and clean. Further changes: - just noticed, do_notify_parent_cldstop() is not safe when called by tracer. The tracee can be killed, released by the tracer's subthread, tracee->parent can exit and its memory can be freed. - when we report the stacked ptrace_event, we must validate it is still valid. The tracer can change options in between, or it can use PTRACE_CONT which (if I understand correctly) should "disable" the report from syscall_exit. - when the tracee reports, say, PTRACE_EVENT_EXEC and the tracer does PTRACE_SYSCALL we should report syscall-exit, even in case the tracee has stopped in utrace_resume() before return to user-mode. --- kernel/ptrace.c | 94 +++++++++++++++++++++++++------------------------------- 1 file changed, 43 insertions(+), 51 deletions(-) --- PU/kernel/ptrace.c~34_CLEANUP_RESUME 2009-09-15 10:34:59.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-15 14:49:47.000000000 +0200 @@ -93,10 +93,6 @@ void __ptrace_link(struct task_struct *c static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */ static int ptrace_attach_task(struct task_struct *tracee, int options); static void ptrace_abort_attach(struct task_struct *tracee); -static void ptrace_wake_up(struct utrace_engine *engine, - struct task_struct *tracee, enum utrace_resume_action action); -static void do_ptrace_notify_stop(struct ptrace_context *context, - struct task_struct *tracee); static void ptrace_detach_task(struct task_struct *child, int sig) { @@ -262,18 +258,6 @@ static void ptrace_clone_attach(struct t set_tsk_thread_flag(child, TIF_SIGPENDING); } -static void ptrace_resume_vfork_done(struct utrace_engine *engine, - struct task_struct *tracee, long data) -{ - ptrace_wake_up(engine, tracee, UTRACE_RESUME); -} - -static void ptrace_resume_clone(struct utrace_engine *engine, - struct task_struct *tracee, long data) -{ - ptrace_wake_up(engine, tracee, UTRACE_RESUME); -} - static u32 ptrace_report_clone(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *parent, @@ -312,7 +296,6 @@ static u32 ptrace_report_clone(enum utra struct ptrace_event *ev = ev_push(context); ev->ev_message = child->pid; - ev->ev_resume = ptrace_resume_clone; ev->ev_code = (event << 8) | SIGTRAP; ret = UTRACE_STOP; @@ -323,7 +306,6 @@ static u32 ptrace_report_clone(enum utra struct ptrace_event *ev = ev_push(context); ev->ev_message = child->pid; - ev->ev_resume = ptrace_resume_vfork_done; ev->ev_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP; ret = UTRACE_STOP; @@ -357,31 +339,6 @@ static u32 ptrace_report_syscall_entry(u return ptrace_report_syscall(UTRACE_SYSCALL_RUN, engine, task); } -// XXX: move this all into ptrace_resume() -static void ptrace_wake_up(struct utrace_engine *engine, - struct task_struct *tracee, - enum utrace_resume_action action) -{ - struct ptrace_context *context = ptrace_context(engine); - unsigned long flags; - - if (!ev_empty(context)) { - do_ptrace_notify_stop(context, tracee); - return; - } - - /* preserve the compatibility bug */ - if (!lock_task_sighand(tracee, &flags)) - return; - tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; - unlock_task_sighand(tracee, &flags); - - // XXX: FIXME!!! racy. - tracee->exit_code = 0; - - utrace_control(tracee, engine, action); -} - static void ptrace_resume_syscall(struct utrace_engine *engine, struct task_struct *tracee, long data) { @@ -392,8 +349,6 @@ static void ptrace_resume_syscall(struct send_sig(data, tracee, 1); read_unlock(&tasklist_lock); } - - ptrace_wake_up(engine, tracee, UTRACE_RESUME); } static u32 ptrace_report_syscall_exit(enum utrace_resume_action action, @@ -1002,6 +957,7 @@ static void do_ptrace_notify_stop(struct WARN_ON(ev->ev_code == 0); ev->ev_code = 0; + // XXX: !!!!!!!! UNSAFE when called by tracer !!!!!!!!!!!!! read_lock(&tasklist_lock); do_notify_parent_cldstop(tracee, CLD_TRAPPED); read_unlock(&tasklist_lock); @@ -1033,6 +989,46 @@ void ptrace_notify_stop(struct task_stru } } +static void ptrace_wake_up(struct utrace_engine *engine, + struct task_struct *tracee, + enum utrace_resume_action action) +{ + unsigned long flags; + + /* preserve the compatibility bug */ + if (!lock_task_sighand(tracee, &flags)) + return; + tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; + unlock_task_sighand(tracee, &flags); + + // XXX: FIXME!!! racy. + tracee->exit_code = 0; + + utrace_control(tracee, engine, action); +} + +static void do_ptrace_resume(struct utrace_engine *engine, + struct task_struct *tracee, + long data) +{ + struct ptrace_context *context = ptrace_context(engine); + + if (!ev_empty(context)) { + struct ptrace_event *ev = ev_pop(context); + + WARN_ON(ev->ev_code); // XXX: debug + if (ev->ev_resume) + ev->ev_resume(engine, tracee, data); + + if (!ev_empty(context)) { + do_ptrace_notify_stop(context, tracee); + return; + } + } + + ptrace_wake_up(engine, tracee, UTRACE_RESUME); +} + static int ptrace_resume(struct task_struct *child, long request, long data) { struct utrace_engine *engine; @@ -1083,12 +1079,7 @@ static int ptrace_resume(struct task_str int event; if (!ev_empty(context)) { - struct ptrace_event *ev = ev_pop(context); - - WARN_ON(ev->ev_code); // XXX: debug - ev->ev_resume(engine, child, data); - ev->ev_resume = NULL; // XXX: debug - + do_ptrace_resume(engine, child, data); utrace_engine_put(engine); return 0; } From oleg at redhat.com Tue Sep 15 18:48:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 15 Sep 2009 20:48:54 +0200 Subject: [PATCH 35] convert ptrace_report_syscall_entry() Message-ID: <20090915184854.GA2382@redhat.com> Change ptrace_report_syscall_entry() to use ptrace_event. I am worried about PTRACE_SYSEMU, I continue to ignore this magic which I don't understand yet... Hopefully I will be able to add the necessary changes later. --- kernel/ptrace.c | 57 ++++++++++++++++++-------------------------------------- 1 file changed, 19 insertions(+), 38 deletions(-) --- PU/kernel/ptrace.c~35_SYSCALL_ENTRY 2009-09-15 14:49:47.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-15 15:45:47.000000000 +0200 @@ -141,12 +141,6 @@ static enum utrace_resume_action ptrace_ return UTRACE_RESUME - ((task->ptrace >> 16) & UTRACE_RESUME_MASK); } -static enum utrace_syscall_action ptrace_syscall_action( - struct task_struct *task) -{ - return (task->ptrace >> 16) & UTRACE_SYSCALL_MASK; -} - /* * Remember which event stop this was. We have to keep a record that * won't be wiped by ptrace_do_wait() when @task->exit_code is cleared. @@ -314,31 +308,6 @@ static u32 ptrace_report_clone(enum utra return ret; } -static u32 ptrace_report_syscall(u32 action, struct utrace_engine *engine, - struct task_struct *task) -{ - struct ptrace_context *context = ptrace_context(engine); - int code = SIGTRAP; - if (context->options & PTRACE_O_TRACESYSGOOD) - code |= 0x80; - return utrace_ptrace_report(action, task, PTRACE_EVENT_SYSCALL, code); -} - -static u32 ptrace_report_syscall_entry(u32 action, - struct utrace_engine *engine, - struct task_struct *task, - struct pt_regs *regs) -{ - /* - * If we're doing PTRACE_SYSEMU, just punt here and report - * at the exit stop instead. - */ - if (ptrace_syscall_action(task)) - return UTRACE_SYSCALL_ABORT | UTRACE_RESUME; - - return ptrace_report_syscall(UTRACE_SYSCALL_RUN, engine, task); -} - static void ptrace_resume_syscall(struct utrace_engine *engine, struct task_struct *tracee, long data) { @@ -351,18 +320,30 @@ static void ptrace_resume_syscall(struct } } -static u32 ptrace_report_syscall_exit(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *task, - struct pt_regs *regs) +static void push_syscall_event(struct ptrace_context *context) { - struct ptrace_context *context = ptrace_context(engine); - struct ptrace_event *ev; + struct ptrace_event *ev = ev_push(context); - ev = ev_push(context); ev->ev_resume = ptrace_resume_syscall; ev->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? (SIGTRAP | 0x80) : SIGTRAP; +} + +static u32 ptrace_report_syscall_entry(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + push_syscall_event(ptrace_context(engine)); + return UTRACE_SYSCALL_RUN | UTRACE_STOP; +} + +static u32 ptrace_report_syscall_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + push_syscall_event(ptrace_context(engine)); return UTRACE_STOP; } From oleg at redhat.com Tue Sep 15 18:48:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 15 Sep 2009 20:48:56 +0200 Subject: [PATCH 36] convert ptrace_report_exec() Message-ID: <20090915184856.GA2385@redhat.com> Change ptrace_report_exec() to use ptrace_event. Now we should fix EXEC/SYSCALL_EXIT interaction wrt PTRACE_CONT/SYSCALL. --- kernel/ptrace.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) --- PU/kernel/ptrace.c~36_REPORT_EXEC 2009-09-15 15:45:47.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-15 18:05:42.000000000 +0200 @@ -194,25 +194,6 @@ static u32 utrace_ptrace_event(struct ta return utrace_ptrace_report(0, task, event, (event << 8) | SIGTRAP); } -static u32 ptrace_report_exec(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *task, - const struct linux_binfmt *fmt, - const struct linux_binprm *bprm, - struct pt_regs *regs) -{ - struct ptrace_context *context = ptrace_context(engine); - - if (context->options & PTRACE_O_TRACEEXEC) - return utrace_ptrace_event(task, PTRACE_EVENT_EXEC, 0); - - /* - * Old-fashioned ptrace'd exec just posts a plain signal. - */ - send_sig(SIGTRAP, task, 0); - return UTRACE_RESUME; -} - static u32 ptrace_report_exit(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *task, @@ -347,6 +328,31 @@ static u32 ptrace_report_syscall_exit(en return UTRACE_STOP; } +static u32 ptrace_report_exec(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct ptrace_context *context = ptrace_context(engine); + struct ptrace_event *ev; + + if (!(context->options & PTRACE_O_TRACEEXEC)) { + /* + * Old-fashioned ptrace'd exec just posts a plain signal. + */ + send_sig(SIGTRAP, task, 0); + return UTRACE_RESUME; + } + + ev = ev_push(context); + ev->ev_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP; + + return UTRACE_STOP; +} + + static u32 ptrace_resumed(struct task_struct *task, struct utrace_engine *engine, siginfo_t *info, struct k_sigaction *return_ka) From oleg at redhat.com Tue Sep 15 18:48:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 15 Sep 2009 20:48:58 +0200 Subject: [PATCH 37] introduce ptrace_event->ev_options Message-ID: <20090915184858.GA2395@redhat.com> When the tracee resumes from TASK_TRACED, context->options can be changed. Introduce ptrace_event->ev_options. If a callback sets ->ev_options != 0, do_ptrace_resume() checks that context->options matches or discards the event. This will be used to validate PTRACE_EVENT_VFORK_DONE and SYSCALL_EXIT reports. --- kernel/ptrace.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) --- PU/kernel/ptrace.c~37_EV_OPTIONS 2009-09-15 18:05:42.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-15 18:06:53.000000000 +0200 @@ -31,6 +31,8 @@ struct ptrace_event { int ev_code; unsigned long ev_message; resume_func_t ev_resume; + + int ev_options; }; struct ptrace_context { @@ -1007,9 +1009,13 @@ static void do_ptrace_resume(struct utra if (ev->ev_resume) ev->ev_resume(engine, tracee, data); - if (!ev_empty(context)) { - do_ptrace_notify_stop(context, tracee); - return; + while (!ev_empty(context)) { + int ev_o = ev_current(context)->ev_options; + if (!ev_o || (ev_o & context->options)) { + do_ptrace_notify_stop(context, tracee); + return; + } + ev_pop(context); } } From oleg at redhat.com Tue Sep 15 18:49:01 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 15 Sep 2009 20:49:01 +0200 Subject: [PATCH 38] make sure PTRACE_CONT "disables" SYSCALL_EXIT report Message-ID: <20090915184901.GA2398@redhat.com> I am a bit surprised there is nothing in ptrace-tests to check CONT/SYSCALL behaviour. I had to write this one: #define WEVENT(s) ((s & 0xFF0000) >> 16) int main(void) { int pid, stat; pid = fork(); if (!pid) { assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); execl("/bin/false", "true", NULL); assert(0); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACEEXEC)); for (;;) { assert(0 == ptrace(PTRACE_SYSCALL, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); if (WEVENT(stat) == PTRACE_EVENT_EXEC) break; } kill(pid, SIGINT); assert(0 == ptrace(PTRACE_CONT, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); // we must see SIGINT, not SYSCALL_EXIT assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGINT); return 0; } If the tracee reports PTRACE_EVENT_EXEC, then it must not report SYSCALL_EXIT if the traces resumes it via PTRACE_CONT. The previous patch introduced ptrace_event->ev_options to filter out unwanted events. But since there is no option for syscall tracing, we add the "fake" PTRACE_O_TRACE_SYSCALL. It is not visible to user space, and this bit is not used outside of ptrace_resume() path. --- kernel/ptrace.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~38_FIX_EXEC_CONT 2009-09-15 18:06:53.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-15 18:36:40.000000000 +0200 @@ -303,10 +303,15 @@ static void ptrace_resume_syscall(struct } } +#define PTRACE_O_TRACE_SYSCALL 0x100 + static void push_syscall_event(struct ptrace_context *context) { struct ptrace_event *ev = ev_push(context); + BUILD_BUG_ON(PTRACE_O_TRACE_SYSCALL & PTRACE_O_MASK); + + ev->ev_options = PTRACE_O_TRACE_SYSCALL; ev->ev_resume = ptrace_resume_syscall; ev->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? (SIGTRAP | 0x80) : SIGTRAP; @@ -998,10 +1003,15 @@ static void ptrace_wake_up(struct utrace static void do_ptrace_resume(struct utrace_engine *engine, struct task_struct *tracee, - long data) + long request, long data) { struct ptrace_context *context = ptrace_context(engine); + if (request == PTRACE_SYSCALL) + context->options |= PTRACE_O_TRACE_SYSCALL; + else + context->options &= ~PTRACE_O_TRACE_SYSCALL; + if (!ev_empty(context)) { struct ptrace_event *ev = ev_pop(context); @@ -1072,7 +1082,7 @@ static int ptrace_resume(struct task_str int event; if (!ev_empty(context)) { - do_ptrace_resume(engine, child, data); + do_ptrace_resume(engine, child, request, data); utrace_engine_put(engine); return 0; } From oleg at redhat.com Tue Sep 15 18:49:03 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 15 Sep 2009 20:49:03 +0200 Subject: [PATCH 39] make sure PTRACE_SYSCALL reports SYSCALL_EXIT Message-ID: <20090915184903.GA2401@redhat.com> Another test-case: #define WEVENT(s) ((s & 0xFF0000) >> 16) int main(void) { int pid, stat; pid = fork(); if (!pid) { assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); execl("/bin/false", "true", NULL); assert(0); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACEEXEC)); for (;;) { assert(0 == ptrace(PTRACE_CONT, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); if (WEVENT(stat) == PTRACE_EVENT_EXEC) break; } kill(pid, SIGINT); assert(0 == ptrace(PTRACE_SYSCALL, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); // must see SYSCALL_EXIT first, assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGTRAP); assert(0 == ptrace(PTRACE_SYSCALL, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); // then SIGINT assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGINT); return 0; } If the tracee enters PTRACE_EVENT_EXEC stop without TIF_SYSCALL_TRACE and then the tracer does ptrace(PTRACE_SYSCALL), we should report SYSCALL_EXIT event. --- kernel/ptrace.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) --- PU/kernel/ptrace.c~39_FIX_EXEC_SYSCALL 2009-09-15 18:36:40.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-15 19:47:50.000000000 +0200 @@ -335,6 +335,17 @@ static u32 ptrace_report_syscall_exit(en return UTRACE_STOP; } +static void ptrace_resume_ck_syscall(struct utrace_engine *engine, + struct task_struct *tracee, long data) +{ + struct ptrace_context *context = ptrace_context(engine); + + if (context->options & PTRACE_O_TRACE_SYSCALL) { + if (ev_empty(context)) + push_syscall_event(context); + } +} + static u32 ptrace_report_exec(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *task, @@ -354,6 +365,7 @@ static u32 ptrace_report_exec(enum utrac } ev = ev_push(context); + ev->ev_resume = ptrace_resume_ck_syscall; ev->ev_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP; return UTRACE_STOP; From oleg at redhat.com Tue Sep 15 18:49:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 15 Sep 2009 20:49:05 +0200 Subject: [PATCH 40] PTRACE_EVENT_VFORK_DONE: set ev_options = PTRACE_O_TRACEVFORKDONE Message-ID: <20090915184905.GA2408@redhat.com> PTRACE_EVENT_VFORK_DONE should not be reported if the tracer cleared PTRACE_O_TRACEVFORKDONE after the tracee stopped in PTRACE_EVENT_VFORK report. Now that we have ptrace_event->ev_options this is trivial. ptrace_report_clone() still needs more changes. I think it is simple to fix it now, but can't we simplify the utrace's behaviour first? utrace_report_clone() does not set utrace->vfork_stop without CLONE_VFORK, this adds some complications. Perhaps we can kill CLONE_VFORK check? --- kernel/ptrace.c | 1 + 1 file changed, 1 insertion(+) --- PU/kernel/ptrace.c~40_EV_O_TRACEVFORKDONE 2009-09-15 19:47:50.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-15 20:40:35.000000000 +0200 @@ -283,6 +283,7 @@ static u32 ptrace_report_clone(enum utra struct ptrace_event *ev = ev_push(context); ev->ev_message = child->pid; + ev->ev_options = PTRACE_O_TRACEVFORKDONE; ev->ev_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP; ret = UTRACE_STOP; From mldireto at tudoemoferta.com.br Tue Sep 15 22:44:26 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Tue, 15 Sep 2009 19:44:26 -0300 Subject: 15 de Setembro, Dia do Cliente. Parabens a todos voces Message-ID: An HTML attachment was scrubbed... URL: From newsletter at usbportugal.com Wed Sep 16 05:55:09 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Wed, 16 Sep 2009 07:55:09 +0200 Subject: =?iso-8859-1?q?J=E1_n=E3o_h=E1_mem=F3ria_de=2E=2E=2ESemana_38?= Message-ID: <6412e56ddf6da445f4a3bce85bd859e9@newsletter2.usbportugal.com> An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Sep 16 18:32:19 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 16 Sep 2009 20:32:19 +0200 Subject: [PATCH 41-43] preliminary ->report_signal() changes Message-ID: <20090916183219.GA15965@redhat.com> OK, signals are not trivial, as expected. Need to think more... Oleg. From oleg at redhat.com Wed Sep 16 18:32:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 16 Sep 2009 20:32:21 +0200 Subject: [PATCH 41] convert ptrace_report_exit() Message-ID: <20090916183221.GA15969@redhat.com> Change ptrace_report_exit() to use ptrace_event. --- kernel/ptrace.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) --- PU/kernel/ptrace.c~41_REPORT_EXIT 2009-09-15 20:40:35.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-16 15:04:48.000000000 +0200 @@ -189,19 +189,19 @@ static u32 utrace_ptrace_report(u32 acti return action | UTRACE_STOP; } -static u32 utrace_ptrace_event(struct task_struct *task, - int event, unsigned long msg) -{ - task->ptrace_message = msg; - return utrace_ptrace_report(0, task, event, (event << 8) | SIGTRAP); -} - static u32 ptrace_report_exit(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *task, long orig_code, long *code) { - return utrace_ptrace_event(task, PTRACE_EVENT_EXIT, *code); + struct ptrace_context *context = ptrace_context(engine); + struct ptrace_event *ev; + + ev = ev_push(context); + ev->ev_message = *code; + ev->ev_code = (PTRACE_EVENT_EXIT << 8) | SIGTRAP; + + return UTRACE_STOP; } static void ptrace_clone_attach(struct task_struct *parent, From oleg at redhat.com Wed Sep 16 18:32:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 16 Sep 2009 20:32:24 +0200 Subject: [PATCH 42] Message-ID: <20090916183224.GA15972@redhat.com> do_ptrace_notify_stop() doesn't change ->ptrace_message if the new value is zero. Not sure what I was thinking about when I wrote this. Remove the "ev->ev_message != 0" check. This is still wrong, I mean this doesn't match the current behaviour. task_struct->ptrace_message will die soon. But I don't understand how compatible the new code should be wrt PTRACE_GETEVENTMSG. Currently: - ptrace_event() always sets ->ptrace_message, this is OK - ptrace_report_syscall() and tracehook_signal_handler() call ptrace_notify() directly which doesn't change ->ptrace_message, this means PTRACE_GETEVENTMSG reports the previous value. This looks a bit strange to me. Should we keep this behaviour? Or can we return 0? Even better, we could put somehing useful into ->ptrace_message, say, syscall number. - jctl stop doesn't change ->ptrace_message too. Again, can the new code return 0? This all is very minor, I am asking just in case. --- kernel/ptrace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) --- PU/kernel/ptrace.c~42_ZERO_PTRACE_MESSAGE 2009-09-16 15:04:48.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-16 15:08:28.000000000 +0200 @@ -956,8 +956,7 @@ static void do_ptrace_notify_stop(struct { struct ptrace_event *ev = ev_current(context); - if (ev->ev_message) - tracee->ptrace_message = ev->ev_message; + tracee->ptrace_message = ev->ev_message; tracee->exit_code = ev->ev_code; // XXX: for debug only From oleg at redhat.com Wed Sep 16 18:32:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 16 Sep 2009 20:32:26 +0200 Subject: [PATCH 43] break ptrace_report_signal() Message-ID: <20090916183226.GA15979@redhat.com> Change ptrace_report_signal() to use ptrace_event. Very preliminary change, just to make the first step. "strace /bin/true" works, and I guess nothing else. And even this wasn't trivial to me ;) Further changes: - remove the old and now unneeded code - teach ptrace_resume() to handle jctl stops - actually implement signals handling, step by step --- kernel/ptrace.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) --- PU/kernel/ptrace.c~43_REPORT_SIGNAL_DRAFT 2009-09-16 15:08:28.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-16 20:14:57.000000000 +0200 @@ -424,6 +424,27 @@ static u32 ptrace_resumed(struct task_st return UTRACE_SIGNAL_DELIVER | resume; } +/* + * XXX: This all is wrong/racy/crashable + */ + +static void ptrace_resume_signal(struct utrace_engine *engine, + struct task_struct *tracee, long data) +{ + siginfo_t *info = tracee->last_siginfo; + + if (WARN_ON(!info)) + return; + + if (info->si_signo != data) { + info->si_signo = data; + info->si_code = SI_USER; + info->si_errno = 0; + info->si_pid = task_pid_vnr(current); + info->si_uid = current_uid(); + } +} + static u32 ptrace_report_signal(u32 action, struct utrace_engine *engine, struct task_struct *task, @@ -433,6 +454,7 @@ static u32 ptrace_report_signal(u32 acti struct k_sigaction *return_ka) { struct ptrace_context *context = ptrace_context(engine); + struct ptrace_event *ev; if (!ev_empty(context)) { WARN_ON(!ev_current(context)->ev_code && !fatal_signal_pending(task)); @@ -442,6 +464,49 @@ static u32 ptrace_report_signal(u32 acti } switch (utrace_signal_action(action)) { + case UTRACE_SIGNAL_HANDLER: + WARN_ON(1); + case UTRACE_SIGNAL_REPORT: + if (!task->last_siginfo) + return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + + if (WARN_ON(task->last_siginfo != info)) + return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + task->last_siginfo = NULL; + + if (!info->si_signo) // debugger cancelled sig + return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + /* + * If the (new) signal is now blocked, requeue it. + */ + if (sigismember(&task->blocked, info->si_signo)) { + send_sig_info(info->si_signo, info, task); + return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + } + + spin_lock_irq(&task->sighand->siglock); + *return_ka = task->sighand->action[info->si_signo - 1]; + spin_unlock_irq(&task->sighand->siglock); + + return UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; + + default: + WARN_ON(task->last_siginfo); + task->last_siginfo = info; + // Make sure the next UTRACE_SIGNAL_REPORT + // will clear ->last_siginfo + utrace_control(task, engine, UTRACE_INTERRUPT); + + ev = ev_push(context); + ev->ev_resume = ptrace_resume_signal; + ev->ev_code = info->si_signo; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; + } + + // everything below is dead + + switch (utrace_signal_action(action)) { default: WARN_ON(ptrace_stop_event(task) && info->si_signo != SIGKILL); break; From oleg at redhat.com Wed Sep 16 18:36:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 16 Sep 2009 20:36:41 +0200 Subject: [PATCH 42] do_ptrace_notify_stop: kill "->ev_message != 0" check In-Reply-To: <20090916183224.GA15972@redhat.com> References: <20090916183224.GA15972@redhat.com> Message-ID: <20090916183641.GA16122@redhat.com> (fix the subject) do_ptrace_notify_stop() doesn't change ->ptrace_message if the new value is zero. Not sure what I was thinking about when I wrote this. Remove the "ev->ev_message != 0" check. This is still wrong, I mean this doesn't match the current behaviour. task_struct->ptrace_message will die soon. But I don't understand how compatible the new code should be wrt PTRACE_GETEVENTMSG. Currently: - ptrace_event() always sets ->ptrace_message, this is OK - ptrace_report_syscall() and tracehook_signal_handler() call ptrace_notify() directly which doesn't change ->ptrace_message, this means PTRACE_GETEVENTMSG reports the previous value. This looks a bit strange to me. Should we keep this behaviour? Or can we return 0? Even better, we could put somehing useful into ->ptrace_message, say, syscall number. - jctl stop doesn't change ->ptrace_message too. Again, can the new code return 0? This all is very minor, I am asking just in case. --- kernel/ptrace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) --- PU/kernel/ptrace.c~42_ZERO_PTRACE_MESSAGE 2009-09-16 15:04:48.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-16 15:08:28.000000000 +0200 @@ -956,8 +956,7 @@ static void do_ptrace_notify_stop(struct { struct ptrace_event *ev = ev_current(context); - if (ev->ev_message) - tracee->ptrace_message = ev->ev_message; + tracee->ptrace_message = ev->ev_message; tracee->exit_code = ev->ev_code; // XXX: for debug only From newsletter at usbportugal.com Thu Sep 17 07:12:42 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Thu, 17 Sep 2009 09:12:42 +0200 Subject: =?iso-8859-1?q?J=E1_n=E3o_h=E1_mem=F3ria_de=2E=2E=2ESemana_38?= Message-ID: <04cd1f2ba1aa30159f0af98c920381b8@newsletter2.usbportugal.com> An HTML attachment was scrubbed... URL: From ssc at sscsoluzioni24.it Thu Sep 17 16:00:58 2009 From: ssc at sscsoluzioni24.it (SSC Srl) Date: Thu, 17 Sep 2009 18:00:58 +0200 Subject: =?utf-8?q?FINANZA_PER_L=E2=80=99IMPRESA=2C_LA_FAMIGLIA_E_LA_PERS?= =?utf-8?q?ONA?= Message-ID: <20090917162317.3785.497969339.swift@192.168.5.5> An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Sep 17 17:30:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 19:30:40 +0200 Subject: problem: utrace-ptrace && jctl stacked stop Message-ID: <20090917173040.GA10129@redhat.com> I seem to find the problem, and I do not see a simple solution. Will try to think more tomorrow with a fresh head, but perhaps you can help. looks like we need some changes in utrace/signal layer. Suppose that a tracee is going to report, say, PTRACE_EVENT_FORK. The callback returns UTRACE_STOP. Of course, utrace_report_xxx() does not do finish_resume_report() or utrace_stop(), we rely on utrace_resume() or utrace_get_signal() which should call utrace_stop() eventually. Now suppose that the tracee's sub-thread initiates the group-stop. In this case the tracee will call do_signal_stop(), without doing utrace_resume/utrace_get_signal. And this means the tracee will stop in TASK_STOPPED with the wrong ->exit_code. ptrace can hook ->report_jctl(), but this can't help. We can do --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1569,6 +1569,10 @@ static int do_signal_stop(int signr) signal_wake_up(t, 0); } } + + // tracehook_notify_jctl() can change ->exit_code. + // If we won't stop ->exit_code will be cleared anyway + current->exit_code = sig->group_exit_code; /* * If there are no other threads in the group, or if there is * a group stop in progress and we are the last to stop, report @@ -1584,7 +1588,6 @@ static int do_signal_stop(int signr) if (sig->group_stop_count) { if (!--sig->group_stop_count) sig->flags = SIGNAL_STOP_STOPPED; - current->exit_code = sig->group_exit_code; __set_current_state(TASK_STOPPED); } spin_unlock_irq(¤t->sighand->siglock); But this doesn't really help too. tracehook_notify_jctl() unlocks ->siglock, if SIGCONT comes in between we can't notice it. In this case the stop reports will be wrong again. What do you think? Oleg. From oleg at redhat.com Thu Sep 17 19:08:11 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 21:08:11 +0200 Subject: [PATCH 44-50] misc Message-ID: <20090917190811.GA25608@redhat.com> Misc changes, more preparations for ptrace_report_signal(). Oleg. From oleg at redhat.com Thu Sep 17 19:08:14 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 21:08:14 +0200 Subject: [PATCH 44] remove the now unneeded code Message-ID: <20090917190814.GA25613@redhat.com> Kill the now unneeded code. >From now ->ptrace is only used for PT_PTRACED and PT_PTRACE_CAP. --- kernel/ptrace.c | 281 +------------------------------------------------------- 1 file changed, 6 insertions(+), 275 deletions(-) --- PU/kernel/ptrace.c~44_KILL_OLD_CODE 2009-09-16 20:14:57.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-17 17:54:06.000000000 +0200 @@ -130,65 +130,6 @@ void __ptrace_unlink(struct task_struct arch_ptrace_untrace(child); } -static void ptrace_set_action(struct task_struct *task, - enum utrace_resume_action action, - enum utrace_syscall_action syscall) -{ - task->ptrace &= ~((UTRACE_SYSCALL_MASK | UTRACE_RESUME_MASK) << 16); - task->ptrace |= ((UTRACE_RESUME - action) | syscall) << 16; -} - -static enum utrace_resume_action ptrace_resume_action(struct task_struct *task) -{ - return UTRACE_RESUME - ((task->ptrace >> 16) & UTRACE_RESUME_MASK); -} - -/* - * Remember which event stop this was. We have to keep a record that - * won't be wiped by ptrace_do_wait() when @task->exit_code is cleared. - * So we store the PTRACE_EVENT_* value in a nybble of @task->ptrace. - */ -static void ptrace_set_stop_event(struct task_struct *task, int event) -{ - task->ptrace &= 0xf0ffffffU; - task->ptrace |= event << 24; -} - -static int ptrace_stop_event(struct task_struct *task) -{ - return (task->ptrace >> 24) & 0xf; -} - -/* - * This doesn't really exist in the user API, but we pick an unused value - * encoded with ptrace_set_stop_event() to record when the last stop was - * for a syscall stop. - */ -#define PTRACE_EVENT_SYSCALL 0xf - -static u32 utrace_ptrace_report(u32 action, struct task_struct *task, - int event, int code) -{ - /* - * Special kludge magic in utrace.c (utrace_stop) sees this - * and calls do_notify_parent_cldstop() for us. This kludge - * is necessary to keep that wakeup after we enter TASK_TRACED. - */ - ptrace_set_action(task, UTRACE_STOP, 0); - - /* - * If we already have a pending stop event, then don't override it. - * We'll simulate this stop when the pending one is cleared, - * in ptrace_resume(), below. - */ - if (ptrace_stop_event(task) == 0) { - ptrace_set_stop_event(task, event); - task->exit_code = code; - } - - return action | UTRACE_STOP; -} - static u32 ptrace_report_exit(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *task, @@ -372,62 +313,9 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_STOP; } - -static u32 ptrace_resumed(struct task_struct *task, - struct utrace_engine *engine, - siginfo_t *info, struct k_sigaction *return_ka) -{ - enum utrace_resume_action resume = ptrace_resume_action(task); - - /* - * If we're stopping, or we haven't reported any signal, - * then we're all done for now. - */ - if (resume == UTRACE_STOP || !task->last_siginfo) - return UTRACE_SIGNAL_REPORT | resume; - - /* - * We're resuming. If there's no signal to deliver, just go. - * If we were given a signal, deliver it now. - */ - WARN_ON(task->last_siginfo != info); - task->last_siginfo = NULL; - if (!task->exit_code) - return UTRACE_SIGNAL_REPORT | resume; - - /* Update the siginfo structure if the signal has - changed. If the debugger wanted something - specific in the siginfo structure then it should - have updated *info via PTRACE_SETSIGINFO. */ - if (task->exit_code != info->si_signo) { - info->si_signo = task->exit_code; - info->si_errno = 0; - info->si_code = SI_USER; - info->si_pid = task_pid_vnr(task->parent); - info->si_uid = __task_cred(task->parent)->uid; - } - - task->exit_code = 0; - - /* - * If the (new) signal is now blocked, requeue it. - */ - if (sigismember(&task->blocked, info->si_signo)) { - send_sig_info(info->si_signo, info, task); - return UTRACE_SIGNAL_IGN | resume; - } - - spin_lock_irq(&task->sighand->siglock); - *return_ka = task->sighand->action[info->si_signo - 1]; - spin_unlock_irq(&task->sighand->siglock); - - return UTRACE_SIGNAL_DELIVER | resume; -} - /* * XXX: This all is wrong/racy/crashable */ - static void ptrace_resume_signal(struct utrace_engine *engine, struct task_struct *tracee, long data) { @@ -503,41 +391,6 @@ static u32 ptrace_report_signal(u32 acti return UTRACE_STOP | UTRACE_SIGNAL_IGN; } - - // everything below is dead - - switch (utrace_signal_action(action)) { - default: - WARN_ON(ptrace_stop_event(task) && info->si_signo != SIGKILL); - break; - case UTRACE_SIGNAL_HANDLER: - WARN_ON(ptrace_stop_event(task)); - /* - * A handler was set up. If we are stepping, pretend - * another SIGTRAP arrived. - */ - if (ptrace_resume_action(task) == UTRACE_SINGLESTEP || - ptrace_resume_action(task) == UTRACE_BLOCKSTEP) { - memset(info, 0, sizeof *info); - info->si_signo = SIGTRAP; - info->si_code = SIGTRAP; - info->si_pid = task_pid_vnr(task); - info->si_uid = __task_cred(task->parent)->uid; - break; - } - /* Fall through. */ - case UTRACE_SIGNAL_REPORT: - /* - * This is not a new signal, but just a notification we - * asked for. Either we're stopping after another report - * like exec or syscall, or we're resuming. - */ - return ptrace_resumed(task, engine, info, return_ka); - } - - WARN_ON(!valid_signal(info->si_signo)); - task->last_siginfo = info; - return utrace_ptrace_report(UTRACE_SIGNAL_IGN, task, 0, info->si_signo); } static u32 ptrace_report_quiesce(u32 action, @@ -552,11 +405,7 @@ static u32 ptrace_report_quiesce(u32 act return UTRACE_STOP; } - if (event == 0) { - task->last_siginfo = NULL; - } - - return ptrace_resume_action(task); + return UTRACE_RESUME; } static void ptrace_release(void *data) @@ -1048,16 +897,11 @@ void ptrace_notify_stop(struct task_stru } context = ptrace_context(engine); - if (!ev_empty(context)) { - do_ptrace_notify_stop(context, tracee); + + if (WARN_ON(ev_empty(context))) return; - } - if (ptrace_resume_action(tracee) == UTRACE_STOP) { - read_lock(&tasklist_lock); - do_notify_parent_cldstop(tracee, CLD_TRAPPED); - read_unlock(&tasklist_lock); - } + do_ptrace_notify_stop(context, tracee); } static void ptrace_wake_up(struct utrace_engine *engine, @@ -1155,121 +999,8 @@ static int ptrace_resume(struct task_str action = UTRACE_SINGLESTEP; } - if (!ret) { - int event; - - if (!ev_empty(context)) { - do_ptrace_resume(engine, child, request, data); - utrace_engine_put(engine); - return 0; - } - - /* - * If there was a non-signal event reported last time, - * we may need to simulate another event that follows - * it, or do some other special case. We'll set @event - * nonzero here if there is an event to simulate. - */ - event = ptrace_stop_event(child); - ptrace_set_stop_event(child, 0); - - switch (event) { - case 0: - break; - - default: - WARN_ON(1); - case PTRACE_EVENT_EXIT: - event = 0; - break; - - case PTRACE_EVENT_FORK: - case PTRACE_EVENT_CLONE: - case PTRACE_EVENT_EXEC: - case PTRACE_EVENT_VFORK_DONE: - /* - * At these events, @data is ignored. - * After these there might be a syscall-exit stop. - */ - if (request == PTRACE_SYSCALL) { - data = SIGTRAP; - if (context->options & PTRACE_O_TRACESYSGOOD) - data |= 0x80; - ptrace_set_stop_event(child, - PTRACE_EVENT_SYSCALL); - } else { - data = 0; - event = 0; - } - break; - - case PTRACE_EVENT_SYSCALL: - /* - * After a syscall stop, @data is treated specially. - * It just queues the signal. - */ - if (data) { - /* XXX: until do_send_sig_info() */ - read_lock(&tasklist_lock); - if (child->signal) - send_sig(data, child, 1); - read_unlock(&tasklist_lock); - } - data = 0; - event = 0; - break; - - case PTRACE_EVENT_VFORK: - WARN_ON(1); - break; - } - - child->exit_code = data; - - ptrace_set_action(child, action, syscall); - - /* - * Whatever action we want to resume with, we need to make - * sure the child gets into ptrace_report_quiesce() so that - * it clears last_siginfo before going back to user mode. - */ - if (child->last_siginfo) - action = UTRACE_REPORT; - - if (event) { - /* - * We have a stacked event. That is, @child is - * already at the last utrace stop point before - * returning to user mode. But the ptrace API - * wants multiple stops on the way out. Here the - * original ptrace would resume the child and have - * to stop again almost immediately. Instead we - * just leave it stopped and simulate the wake-up - * and new stop by notifying the parent, i.e. - * current's own thread group. - */ - read_lock(&tasklist_lock); - do_notify_parent_cldstop(child, CLD_TRAPPED); - read_unlock(&tasklist_lock); - } else { - unsigned long flags; - - if (lock_task_sighand(child, &flags)) { - child->signal->flags &= ~SIGNAL_STOP_STOPPED; - unlock_task_sighand(child, &flags); - } - - /* - * To resume with a signal we must arrange - * to enter ptrace_report_signal(). - */ - if (data) - action = UTRACE_INTERRUPT; - - if (utrace_control(child, engine, action)) - ret = -ESRCH; - } - } + if (!ret) + do_ptrace_resume(engine, child, request, data); utrace_engine_put(engine); From oleg at redhat.com Thu Sep 17 19:08:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 21:08:17 +0200 Subject: [PATCH 45] ptrace_report_quiesce() can't trust fatal_signal_pending() Message-ID: <20090917190817.GA25620@redhat.com> SIGKILL can be already dequeued if we are called from do_exit() path. This debugging check should die, but I'd like to keep it for now. --- kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- PU/kernel/ptrace.c~45_STOP_WARNINGS 2009-09-17 17:54:06.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-17 18:41:47.000000000 +0200 @@ -401,7 +401,7 @@ static u32 ptrace_report_quiesce(u32 act struct ptrace_context *context = ptrace_context(engine); if (!ev_empty(context)) { - WARN_ON(!ev_current(context)->ev_code && !fatal_signal_pending(task)); + WARN_ON(!ev_current(context)->ev_code && !fatal_signal_pending(task) && !(task->flags & PF_EXITING)); return UTRACE_STOP; } From oleg at redhat.com Thu Sep 17 19:08:19 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 21:08:19 +0200 Subject: [PATCH 46] pretens ptrace_detach(sig) works Message-ID: <20090917190819.GA25623@redhat.com> The current "implementation" of ptrace_report_signa() is almost a joke, but still I was surprized the fatal signals do not work under strace. I spent a lot of time before I realized this doesn't work from the very beginning: I didn't know that when strace notices the fatal signal, it doesn't resume the tracee but simply does ptrace(DETACH, sig). Change ptrace_detach() to send the signal if data != 0. This is not correct of course, but a bit better than nothing. Another reason for this change: from now ptrace doesn't abuse->exit_code, we only set it for do_wait() in do_ptrace_notify_stop(), and clear it in ptrace_resume(). --- kernel/ptrace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~46_DETACH_SEND_SIG 2009-09-17 18:41:47.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-17 19:33:34.000000000 +0200 @@ -705,8 +705,9 @@ static void ptrace_do_detach(struct task detach = tracee->ptrace != 0; release = false; if (likely(detach)) { - if (valid_signal(data)) - tracee->exit_code = data; + // XXX: temporary hack + if (data && valid_signal(data)) + send_sig(data, tracee, 1); release = __ptrace_detach(current, tracee); } write_unlock_irq(&tasklist_lock); From oleg at redhat.com Thu Sep 17 19:08:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 21:08:21 +0200 Subject: [PATCH 47] mv task_struct->last_siginfo ptrace_context->siginfo Message-ID: <20090917190821.GA25631@redhat.com> Introduce ptrace_context->siginfo. Of course the usage of context->siginfo is still wrong. But this change is important, previously PTRACE_DETACH can leave the tracee with ->last_siginfo != NULL. ptrace_getsiginfo/ptrace_setsiginfo need cleanups (and fixes). I think we need ptrace_lookup_engine() helper, and ptrace_request() should find the engine and pass it to ptrace_resume/etc. --- kernel/ptrace.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) --- PU/kernel/ptrace.c~47_CTX_SIGINFO 2009-09-17 19:33:34.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-17 20:13:24.000000000 +0200 @@ -38,6 +38,8 @@ struct ptrace_event { struct ptrace_context { int options; + siginfo_t *siginfo; + struct ptrace_event ev_array[2]; unsigned int ev_first, ev_last; }; @@ -319,7 +321,7 @@ static u32 ptrace_report_exec(enum utrac static void ptrace_resume_signal(struct utrace_engine *engine, struct task_struct *tracee, long data) { - siginfo_t *info = tracee->last_siginfo; + siginfo_t *info = ptrace_context(engine)->siginfo; if (WARN_ON(!info)) return; @@ -355,12 +357,12 @@ static u32 ptrace_report_signal(u32 acti case UTRACE_SIGNAL_HANDLER: WARN_ON(1); case UTRACE_SIGNAL_REPORT: - if (!task->last_siginfo) + if (!context->siginfo) return UTRACE_RESUME | UTRACE_SIGNAL_IGN; - if (WARN_ON(task->last_siginfo != info)) + if (WARN_ON(context->siginfo != info)) return UTRACE_RESUME | UTRACE_SIGNAL_IGN; - task->last_siginfo = NULL; + context->siginfo = NULL; if (!info->si_signo) // debugger cancelled sig return UTRACE_RESUME | UTRACE_SIGNAL_IGN; @@ -379,10 +381,10 @@ static u32 ptrace_report_signal(u32 acti return UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; default: - WARN_ON(task->last_siginfo); - task->last_siginfo = info; + WARN_ON(context->siginfo); + context->siginfo = info; // Make sure the next UTRACE_SIGNAL_REPORT - // will clear ->last_siginfo + // will clear context->siginfo utrace_control(task, engine, UTRACE_INTERRUPT); ev = ev_push(context); @@ -817,33 +819,47 @@ static int ptrace_set_options(struct tas static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info) { + struct utrace_engine *engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); unsigned long flags; int error = -ESRCH; + if (IS_ERR(engine)) + return error; + if (lock_task_sighand(child, &flags)) { error = -EINVAL; - if (likely(child->last_siginfo != NULL)) { - *info = *child->last_siginfo; + if (likely(ptrace_context(engine)->siginfo != NULL)) { + *info = *ptrace_context(engine)->siginfo; error = 0; } unlock_task_sighand(child, &flags); } + + utrace_engine_put(engine); return error; } static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) { + struct utrace_engine *engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); unsigned long flags; int error = -ESRCH; + if (IS_ERR(engine)) + return error; + if (lock_task_sighand(child, &flags)) { error = -EINVAL; - if (likely(child->last_siginfo != NULL)) { - *child->last_siginfo = *info; + if (likely(ptrace_context(engine)->siginfo != NULL)) { + *ptrace_context(engine)->siginfo = *info; error = 0; } unlock_task_sighand(child, &flags); } + + utrace_engine_put(engine); return error; } From oleg at redhat.com Thu Sep 17 19:08:23 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 21:08:23 +0200 Subject: [PATCH 48] introduce ptrace_lookup_engine() Message-ID: <20090917190823.GA25634@redhat.com> The multi-line utrace_attach_task(a lot of args) looks really annoing, add the trivial helper, ptrace_lookup_engine(tracee). --- kernel/ptrace.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) --- PU/kernel/ptrace.c~48_PTRACE_LOOKUP_ENGINE 2009-09-17 20:13:24.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-17 20:35:09.000000000 +0200 @@ -98,13 +98,17 @@ static const struct utrace_engine_ops pt static int ptrace_attach_task(struct task_struct *tracee, int options); static void ptrace_abort_attach(struct task_struct *tracee); +static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee) +{ + return utrace_attach_task(tracee, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); +} + static void ptrace_detach_task(struct task_struct *child, int sig) { - struct utrace_engine *engine; + struct utrace_engine *engine = ptrace_lookup_engine(child); int ret; - engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); if (unlikely(IS_ERR(engine))) return; @@ -493,8 +497,7 @@ int ptrace_check_attach(struct task_stru if (child->parent != current) return -ESRCH; - engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); + engine = ptrace_lookup_engine(child); if (IS_ERR(engine)) return -ESRCH; @@ -805,10 +808,8 @@ int ptrace_writedata(struct task_struct static int ptrace_set_options(struct task_struct *child, long data) { - struct utrace_engine *engine; + struct utrace_engine *engine = ptrace_lookup_engine(child); - engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); if (likely(!IS_ERR(engine))) { __ptrace_set_options(child, engine, data & PTRACE_O_MASK); utrace_engine_put(engine); @@ -819,8 +820,7 @@ static int ptrace_set_options(struct tas static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info) { - struct utrace_engine *engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); + struct utrace_engine *engine = ptrace_lookup_engine(child); unsigned long flags; int error = -ESRCH; @@ -842,8 +842,7 @@ static int ptrace_getsiginfo(struct task static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) { - struct utrace_engine *engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); + struct utrace_engine *engine = ptrace_lookup_engine(child); unsigned long flags; int error = -ESRCH; @@ -902,11 +901,9 @@ static void do_ptrace_notify_stop(struct void ptrace_notify_stop(struct task_struct *tracee) { - struct utrace_engine *engine; + struct utrace_engine *engine = ptrace_lookup_engine(tracee); struct ptrace_context *context; - engine = utrace_attach_task(tracee, UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); if (IS_ERR(engine)) { // XXX: temporary check, wrong with mutlitracing WARN_ON(tracee->state != TASK_RUNNING); @@ -914,10 +911,8 @@ void ptrace_notify_stop(struct task_stru } context = ptrace_context(engine); - if (WARN_ON(ev_empty(context))) return; - do_ptrace_notify_stop(context, tracee); } @@ -981,8 +976,7 @@ static int ptrace_resume(struct task_str if (!valid_signal(data)) return -EIO; - engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); + engine = ptrace_lookup_engine(child); if (IS_ERR(engine)) return -ESRCH; From oleg at redhat.com Thu Sep 17 19:08:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 21:08:26 +0200 Subject: [PATCH 49] change ptrace_resume() to have the single "return" Message-ID: <20090917190826.GA25637@redhat.com> No changes in ptrace.o, change ptrace_resume() to not return from inside switch(). --- kernel/ptrace.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) --- PU/kernel/ptrace.c~49_PTRACE_REQUEST_ENGINE 2009-09-17 20:35:09.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-17 20:46:55.000000000 +0200 @@ -1021,16 +1021,18 @@ static int ptrace_resume(struct task_str int ptrace_request(struct task_struct *child, long request, long addr, long data) { - int ret = -EIO; siginfo_t siginfo; + int ret; switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: - return generic_ptrace_peekdata(child, addr, data); + ret = generic_ptrace_peekdata(child, addr, data); + break; case PTRACE_POKETEXT: case PTRACE_POKEDATA: - return generic_ptrace_pokedata(child, addr, data); + ret = generic_ptrace_pokedata(child, addr, data); + break; #ifdef PTRACE_OLDSETOPTIONS case PTRACE_OLDSETOPTIONS: @@ -1073,14 +1075,17 @@ int ptrace_request(struct task_struct *c #endif case PTRACE_SYSCALL: case PTRACE_CONT: - return ptrace_resume(child, request, data); + ret = ptrace_resume(child, request, data); + break; case PTRACE_KILL: - if (child->exit_state) /* already dead */ - return 0; - return ptrace_resume(child, request, SIGKILL); + ret = 0; + if (!child->exit_state) /* already dead */ + ret = ptrace_resume(child, request, SIGKILL); + break; default: + ret = -EIO; break; } From oleg at redhat.com Thu Sep 17 19:08:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 21:08:28 +0200 Subject: [PATCH 50] ptrace_request: use ptrace_lookup_engine() Message-ID: <20090917190828.GA25644@redhat.com> Change ptrace_request() to find utrace_engine and pass it to callees. --- kernel/ptrace.c | 63 +++++++++++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 37 deletions(-) --- PU/kernel/ptrace.c~50_PTRACE_REQUEST_LOOKUP_ENGINE 2009-09-17 20:46:55.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-17 21:03:11.000000000 +0200 @@ -806,27 +806,20 @@ int ptrace_writedata(struct task_struct return copied; } -static int ptrace_set_options(struct task_struct *child, long data) +static int ptrace_set_options(struct utrace_engine *engine, + struct task_struct *child, long data) { - struct utrace_engine *engine = ptrace_lookup_engine(child); - - if (likely(!IS_ERR(engine))) { - __ptrace_set_options(child, engine, data & PTRACE_O_MASK); - utrace_engine_put(engine); - } + __ptrace_set_options(child, engine, data & PTRACE_O_MASK); return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; } -static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info) +static int ptrace_getsiginfo(struct utrace_engine *engine, + struct task_struct *child, siginfo_t *info) { - struct utrace_engine *engine = ptrace_lookup_engine(child); unsigned long flags; int error = -ESRCH; - if (IS_ERR(engine)) - return error; - if (lock_task_sighand(child, &flags)) { error = -EINVAL; if (likely(ptrace_context(engine)->siginfo != NULL)) { @@ -836,19 +829,15 @@ static int ptrace_getsiginfo(struct task unlock_task_sighand(child, &flags); } - utrace_engine_put(engine); return error; } -static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) +static int ptrace_setsiginfo(struct utrace_engine *engine, + struct task_struct *child, const siginfo_t *info) { - struct utrace_engine *engine = ptrace_lookup_engine(child); unsigned long flags; int error = -ESRCH; - if (IS_ERR(engine)) - return error; - if (lock_task_sighand(child, &flags)) { error = -EINVAL; if (likely(ptrace_context(engine)->siginfo != NULL)) { @@ -858,7 +847,6 @@ static int ptrace_setsiginfo(struct task unlock_task_sighand(child, &flags); } - utrace_engine_put(engine); return error; } @@ -965,10 +953,9 @@ static void do_ptrace_resume(struct utra ptrace_wake_up(engine, tracee, UTRACE_RESUME); } -static int ptrace_resume(struct task_struct *child, long request, long data) +static int ptrace_resume(struct utrace_engine *engine, + struct task_struct *child, long request, long data) { - struct utrace_engine *engine; - struct ptrace_context *context; enum utrace_resume_action action; enum utrace_syscall_action syscall; int ret = 0; @@ -976,12 +963,6 @@ static int ptrace_resume(struct task_str if (!valid_signal(data)) return -EIO; - engine = ptrace_lookup_engine(child); - if (IS_ERR(engine)) - return -ESRCH; - - context = ptrace_context(engine); - syscall = UTRACE_SYSCALL_RUN; #ifdef PTRACE_SYSEMU if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) @@ -1013,17 +994,19 @@ static int ptrace_resume(struct task_str if (!ret) do_ptrace_resume(engine, child, request, data); - utrace_engine_put(engine); - return ret; } int ptrace_request(struct task_struct *child, long request, long addr, long data) { + struct utrace_engine *engine = ptrace_lookup_engine(child); siginfo_t siginfo; int ret; + if (unlikely(IS_ERR(engine))) + return -ESRCH; + switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: @@ -1038,14 +1021,14 @@ int ptrace_request(struct task_struct *c case PTRACE_OLDSETOPTIONS: #endif case PTRACE_SETOPTIONS: - ret = ptrace_set_options(child, data); + ret = ptrace_set_options(engine, child, data); break; case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned long __user *) data); break; case PTRACE_GETSIGINFO: - ret = ptrace_getsiginfo(child, &siginfo); + ret = ptrace_getsiginfo(engine, child, &siginfo); if (!ret) ret = copy_siginfo_to_user((siginfo_t __user *) data, &siginfo); @@ -1056,7 +1039,7 @@ int ptrace_request(struct task_struct *c sizeof siginfo)) ret = -EFAULT; else - ret = ptrace_setsiginfo(child, &siginfo); + ret = ptrace_setsiginfo(engine, child, &siginfo); break; case PTRACE_DETACH: /* detach a process that was attached. */ @@ -1075,13 +1058,13 @@ int ptrace_request(struct task_struct *c #endif case PTRACE_SYSCALL: case PTRACE_CONT: - ret = ptrace_resume(child, request, data); + ret = ptrace_resume(engine, child, request, data); break; case PTRACE_KILL: ret = 0; if (!child->exit_state) /* already dead */ - ret = ptrace_resume(child, request, SIGKILL); + ret = ptrace_resume(engine, child, request, SIGKILL); break; default: @@ -1089,6 +1072,7 @@ int ptrace_request(struct task_struct *c break; } + utrace_engine_put(engine); return ret; } @@ -1182,11 +1166,15 @@ int generic_ptrace_pokedata(struct task_ int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { + struct utrace_engine *engine = ptrace_lookup_engine(child); compat_ulong_t __user *datap = compat_ptr(data); compat_ulong_t word; siginfo_t siginfo; int ret; + if (unlikely(IS_ERR(engine))) + return -ESRCH; + switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: @@ -1208,7 +1196,7 @@ int compat_ptrace_request(struct task_st break; case PTRACE_GETSIGINFO: - ret = ptrace_getsiginfo(child, &siginfo); + ret = ptrace_getsiginfo(engine, child, &siginfo); if (!ret) ret = copy_siginfo_to_user32( (struct compat_siginfo __user *) datap, @@ -1221,13 +1209,14 @@ int compat_ptrace_request(struct task_st &siginfo, (struct compat_siginfo __user *) datap)) ret = -EFAULT; else - ret = ptrace_setsiginfo(child, &siginfo); + ret = ptrace_setsiginfo(engine, child, &siginfo); break; default: ret = ptrace_request(child, request, addr, data); } + utrace_engine_put(engine); return ret; } From oleg at redhat.com Thu Sep 17 19:14:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 17 Sep 2009 21:14:05 +0200 Subject: problem: utrace-ptrace && jctl stacked stop In-Reply-To: <20090917173040.GA10129@redhat.com> References: <20090917173040.GA10129@redhat.com> Message-ID: <20090917191405.GA25722@redhat.com> On 09/17, Oleg Nesterov wrote: > > I seem to find the problem, and I do not see a simple solution. > Will try to think more tomorrow with a fresh head, but perhaps > you can help. looks like we need some changes in utrace/signal > layer. > > Suppose that a tracee is going to report, say, PTRACE_EVENT_FORK. > The callback returns UTRACE_STOP. Of course, utrace_report_xxx() > does not do finish_resume_report() or utrace_stop(), we rely on > utrace_resume() or utrace_get_signal() which should call utrace_stop() > eventually. > > Now suppose that the tracee's sub-thread initiates the group-stop. > In this case the tracee will call do_signal_stop(), without doing > utrace_resume/utrace_get_signal. And this means the tracee will > stop in TASK_STOPPED with the wrong ->exit_code. > > ptrace can hook ->report_jctl(), but this can't help. We can do > > --- a/kernel/signal.c > +++ b/kernel/signal.c > @@ -1569,6 +1569,10 @@ static int do_signal_stop(int signr) > signal_wake_up(t, 0); > } > } > + > + // tracehook_notify_jctl() can change ->exit_code. > + // If we won't stop ->exit_code will be cleared anyway > + current->exit_code = sig->group_exit_code; > /* > * If there are no other threads in the group, or if there is > * a group stop in progress and we are the last to stop, report > @@ -1584,7 +1588,6 @@ static int do_signal_stop(int signr) > if (sig->group_stop_count) { > if (!--sig->group_stop_count) > sig->flags = SIGNAL_STOP_STOPPED; > - current->exit_code = sig->group_exit_code; > __set_current_state(TASK_STOPPED); > } > spin_unlock_irq(¤t->sighand->siglock); > > But this doesn't really help too. tracehook_notify_jctl() unlocks > ->siglock, if SIGCONT comes in between we can't notice it. In this > case the stop reports will be wrong again. > > What do you think? I am starting to think the best option is to call utrace_get_signal() before "if (unlikely(signal->group_stop_count > 0)" check. utrace_get_signal should check ->group_stop_count before dequeue_signal(), if it is true we pass the special event/result ->report_signal(). Oleg. From roland at redhat.com Fri Sep 18 01:22:12 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Sep 2009 18:22:12 -0700 (PDT) Subject: [PATCH 50] ptrace_request: use ptrace_lookup_engine() In-Reply-To: Oleg Nesterov's message of Thursday, 17 September 2009 21:08:28 +0200 <20090917190828.GA25644@redhat.com> References: <20090917190828.GA25644@redhat.com> Message-ID: <20090918012212.80F4B154D@magilla.sf.frob.com> It would be more consistent with e.g. utrace APIs to make the order of arguments task, engine (obviously a trivial thing). Thanks, Roland From roland at redhat.com Thu Sep 17 22:13:10 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Sep 2009 15:13:10 -0700 (PDT) Subject: [PATCH 37] introduce ptrace_event->ev_options In-Reply-To: Oleg Nesterov's message of Tuesday, 15 September 2009 20:48:58 +0200 <20090915184858.GA2395@redhat.com> References: <20090915184858.GA2395@redhat.com> Message-ID: <20090917221310.B8A7570@magilla.sf.frob.com> > When the tracee resumes from TASK_TRACED, context->options can be changed. > > Introduce ptrace_event->ev_options. If a callback sets ->ev_options != 0, > do_ptrace_resume() checks that context->options matches or discards the > event. IMHO this hair is a pretty clear indication that the "queued reports" model is just not the right model. You have all this new complexity because of the model that you queue the details of the report at event time, but in reality much of that determination belongs at report time rather than event time. I'm merging everything just to let you make progress how you like. But I think you need to answer my earlier question about the motivation for this whole plan. I think the reality of what is actually required is substantially simpler than the complexities entailed in this abstraction. Thanks, Roland From roland at redhat.com Thu Sep 17 22:35:38 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Sep 2009 15:35:38 -0700 (PDT) Subject: [PATCH 41] convert ptrace_report_exit() In-Reply-To: Oleg Nesterov's message of Wednesday, 16 September 2009 20:32:21 +0200 <20090916183221.GA15969@redhat.com> References: <20090916183221.GA15969@redhat.com> Message-ID: <20090917223538.9959570@magilla.sf.frob.com> > Change ptrace_report_exit() to use ptrace_event. Leaving aside my reservations about the whole plan, this is the most concise example yet of how you are introducing duplicate boilerplate all over the place where it ought to be written to share the code. Even repeating "(event << 8) | SIGTRAP" is obviously ugly. utrace_ptrace_event is the right abstraction. Add the other field initializers as arguments. Thanks, Roland From roland at redhat.com Thu Sep 17 22:26:51 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Sep 2009 15:26:51 -0700 (PDT) Subject: [PATCH 39] make sure PTRACE_SYSCALL reports SYSCALL_EXIT In-Reply-To: Oleg Nesterov's message of Tuesday, 15 September 2009 20:49:03 +0200 <20090915184903.GA2401@redhat.com> References: <20090915184903.GA2401@redhat.com> Message-ID: <20090917222651.717B870@magilla.sf.frob.com> > If the tracee enters PTRACE_EVENT_EXEC stop without TIF_SYSCALL_TRACE > and then the tracer does ptrace(PTRACE_SYSCALL), we should report > SYSCALL_EXIT event. Indeed. But note that without PTRACE_O_TRACEEXEC, we do not have an "event stop", but just send ourselves a normal signal. In that case, a PTRACE_SYSCALL resuming from the entry stop for execve will hit the exit stop first (just like any other syscall), and then dequeue the signal. Thanks, Roland From roland at redhat.com Thu Sep 17 22:24:28 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Sep 2009 15:24:28 -0700 (PDT) Subject: [PATCH 35] convert ptrace_report_syscall_entry() In-Reply-To: Oleg Nesterov's message of Tuesday, 15 September 2009 20:48:54 +0200 <20090915184854.GA2382@redhat.com> References: <20090915184854.GA2382@redhat.com> Message-ID: <20090917222428.1CE1470@magilla.sf.frob.com> > I am worried about PTRACE_SYSEMU, I continue to ignore this magic > which I don't understand yet... Hopefully I will be able to add the > necessary changes later. It should not be a big complexity. The semantics is that the entry report always does like UTRACE_SYSCALL_ABORT to skip the actual call, and then there is no exit report. (Since ptrace doesn't distinguish entry and exit reports, you can make the actual stop and report happen either in the entry spot or the exit spot, whatever is easiest in the implementation.) Thanks, Roland From roland at redhat.com Thu Sep 17 22:39:45 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Sep 2009 15:39:45 -0700 (PDT) Subject: [PATCH 42] do_ptrace_notify_stop: kill "->ev_message != 0" check In-Reply-To: Oleg Nesterov's message of Wednesday, 16 September 2009 20:36:41 +0200 <20090916183641.GA16122@redhat.com> References: <20090916183224.GA15972@redhat.com> <20090916183641.GA16122@redhat.com> Message-ID: <20090917223945.1DD7170@magilla.sf.frob.com> > do_ptrace_notify_stop() doesn't change ->ptrace_message if the new > value is zero. Not sure what I was thinking about when I wrote this. Perhaps you were thinking of the upstream code before tracehook.h was introduced. Ancient code left whatever was in ptrace_message before there for the "0" cases. When I made everything use ptrace_event(), the semantics changed to yield 0 rather than last-event's-unrelated-value for PTRACE_GETEVENTMSG after events that don't really have a message word. > - ptrace_event() always sets ->ptrace_message, this is OK Right. > - ptrace_report_syscall() and tracehook_signal_handler() > call ptrace_notify() directly which doesn't change > ->ptrace_message, this means PTRACE_GETEVENTMSG reports > the previous value. > > This looks a bit strange to me. Should we keep this > behaviour? Or can we return 0? Even better, we could > put somehing useful into ->ptrace_message, say, syscall > number. I think we can set it to 0. It's the same change we made by introducing ptrace_event() for the other cases, and nobody complained. > - jctl stop doesn't change ->ptrace_message too. Again, > can the new code return 0? I think so. > This all is very minor, I am asking just in case. Right, diligence appreciated! It might be wisest to send the trivial changes to clear ptrace_message in those cases upstream first so that we match the semantics exactly. Thanks, Roland From roland at redhat.com Thu Sep 17 22:17:24 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Sep 2009 15:17:24 -0700 (PDT) Subject: [PATCH 38] make sure PTRACE_CONT "disables" SYSCALL_EXIT report In-Reply-To: Oleg Nesterov's message of Tuesday, 15 September 2009 20:49:01 +0200 <20090915184901.GA2398@redhat.com> References: <20090915184901.GA2398@redhat.com> Message-ID: <20090917221724.D06E970@magilla.sf.frob.com> > I am a bit surprised there is nothing in ptrace-tests to check > CONT/SYSCALL behaviour. I had to write this one: That suite has grown only through regression tests for bugs that we've noticed. So it doesn't test a case if my past implementations never broke that case, nor if a regression never broke the assumptions of gdb, strace, or other actual applications (including my old ntrace test suite, which did a few things with ptrace not otherwise common). For any test case you found useful, please add it to the ptrace-tests suite. Jan can help you get it in the right form and get it committed. Or if he would prefer not to keep maintaining that suite, we can get you set up on sourceware so you can do it yourself. Thanks, Roland From roland at redhat.com Mon Sep 14 17:19:04 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 14 Sep 2009 10:19:04 -0700 (PDT) Subject: [PATCH 33] implement stacked stop events In-Reply-To: Oleg Nesterov's message of Monday, 14 September 2009 12:18:36 +0200 <20090914101836.GA26416@redhat.com> References: <20090914060633.GA8446@redhat.com> <20090914083251.BB2E073F8@magilla.sf.frob.com> <20090914101836.GA26416@redhat.com> Message-ID: <20090914171904.CBB6495@magilla.sf.frob.com> > Basically, we have ev_push() and ev_pop(), that is all. I don't mean it's hard to understand what the code does. It's clear enough that it's a simple ring buffer scheme. But just having that extra data structure is extra complexity and storage even so. It's quite overly general for what is really needed. > We need to record the values for task->exit_code and task->ptrace_message > at least. _Perhaps_, we also need to record the bit from context->options, > I am not sure. Do you really need to store more than one ptrace_message word? I don't think so. Let's think about the cases. Where is there a "stacked" event that has a message word? I think that's only PTRACE_EVENT_VFORK_DONE. Its message word is the child's PID, which is the same word set previously by the PTRACE_EVENT_VFORK report. (If there is no PTRACE_EVENT_VFORK stop requested, then you can just store that word anyway so it's there in case of PTRACE_EVENT_VFORK_DONE later.) Why do you think you might need to record any option bits? The past state of option bits should not matter. > Yes, this is mostly simple. But probably sometimes we need some fixups > when chane the state. Again, I am not sure, dind't sleep today. I got your message last night but decided to sleep before replying. :-) Thanks, Roland From roland at redhat.com Thu Sep 17 22:31:30 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Sep 2009 15:31:30 -0700 (PDT) Subject: [PATCH 40] PTRACE_EVENT_VFORK_DONE: set ev_options = PTRACE_O_TRACEVFORKDONE In-Reply-To: Oleg Nesterov's message of Tuesday, 15 September 2009 20:49:05 +0200 <20090915184905.GA2408@redhat.com> References: <20090915184905.GA2408@redhat.com> Message-ID: <20090917223130.BDFED70@magilla.sf.frob.com> > ptrace_report_clone() still needs more changes. I think it is simple to > fix it now, but can't we simplify the utrace's behaviour first? > > utrace_report_clone() does not set utrace->vfork_stop without CLONE_VFORK, > this adds some complications. Perhaps we can kill CLONE_VFORK check? Please explain exactly what difference you want to see in the utrace API. Just talking about implementation details is confusing. The API today is that UTRACE_STOP from report_clone always guarantees a prompt stop. For CLONE_VFORK, that means it has to stop before the vfork-wait, so before syscall-exit. Without CLONE_VFORK, the usual rule applies: nothing user-visible happens until returning to user mode, so there is no stop. Well, the one user-visible thing that happens is the return value register getting set (right before the syscall-exit event). Thanks, Roland From roland at redhat.com Thu Sep 17 21:56:35 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Sep 2009 14:56:35 -0700 (PDT) Subject: tracehooks changes && 2.6.32 -mm merge plans In-Reply-To: Oleg Nesterov's message of Thursday, 17 September 2009 22:46:56 +0200 <20090917204656.GC29346@redhat.com> References: <20090915161535.db0a6904.akpm@linux-foundation.org> <20090917204656.GC29346@redhat.com> Message-ID: <20090917215635.73CE89A5@magilla.sf.frob.com> > On 09/15, Andrew Morton wrote: > > > > #signals-tracehook_notify_jctl-change.patch: needs changelog folding too > > signals-tracehook_notify_jctl-change.patch > > signals-tracehook_notify_jctl-change-do_signal_stop-do-not-call-tracehook_notify_jctl-in-task_stopped-state.patch > > #signals-introduce-tracehook_finish_jctl-helper.patch: fold into signals-tracehook_notify_jctl-change.patch > > signals-introduce-tracehook_finish_jctl-helper.patch > > I think these make sense anyway, Agreed. > > utrace-core.patch > > > > utrace. What's happening with this? > > (since Roland didn't reply yet) > > I guess this patch should be updated. We do have a newer version now with various fixes and clean-ups. But the current version does not play nice with ptrace (does not even exclude ptrace any more). Without at least the ptrace exclusion, using both utrace modules and ptrace might lead to a confused kernel or BUG_ON hits. Past feedback tells us that we need some in-tree users of the utrace API to get merged too. Frank was working on such a thing, and the IBM folks may have another such thing, but I don't know the present status of those modules. Oleg is working feverishly on revamping ptrace using utrace. Other past feedback has suggested this is what people want to see to justify utrace going in. That ptrace work is still a bit away from being ready even for -mm submission. We're pretty sure that we will do some more changes in the utrace core to make that work well, so utrace merged first would be sure to get more changes later (probably including some API differences). Thanks, Roland From newsletter at usbportugal.com Fri Sep 18 07:27:20 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Fri, 18 Sep 2009 09:27:20 +0200 Subject: =?iso-8859-1?q?J=E1_n=E3o_h=E1_mem=F3ria_de=2E=2E=2ESemana_38?= Message-ID: <85ecc845740f0bb0324882589a4cddca@newsletter1.usbportugal.com> An HTML attachment was scrubbed... URL: From jan.kratochvil at redhat.com Fri Sep 18 09:14:00 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Fri, 18 Sep 2009 11:14:00 +0200 Subject: [PATCH 38] make sure PTRACE_CONT "disables" SYSCALL_EXIT report In-Reply-To: <20090917221724.D06E970@magilla.sf.frob.com> References: <20090915184901.GA2398@redhat.com> <20090917221724.D06E970@magilla.sf.frob.com> Message-ID: <20090918091359.GA11742@host0.dyn.jankratochvil.net> On Fri, 18 Sep 2009 00:17:24 +0200, Roland McGrath wrote: > For any test case you found useful, please add it to the ptrace-tests > suite. Jan can help you get it in the right form and get it committed. Checked-in as: http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/tests/ptrace-tests/tests/sigint-before-syscall-exit.c?cvsroot=systemtap > Or if he would prefer not to keep maintaining that suite, we can get you > set up on sourceware so you can do it yourself. With current utrace it is no longer a fulltime assignment so it is OK this way. Thanks, Jan From roland at redhat.com Fri Sep 18 09:49:47 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 18 Sep 2009 02:49:47 -0700 (PDT) Subject: problem: utrace-ptrace && jctl stacked stop In-Reply-To: Oleg Nesterov's message of Thursday, 17 September 2009 21:14:05 +0200 <20090917191405.GA25722@redhat.com> References: <20090917173040.GA10129@redhat.com> <20090917191405.GA25722@redhat.com> Message-ID: <20090918094947.F3D5E278D@magilla.sf.frob.com> I'll point out that the only symptom that matters to ptrace is ->exit_code and that issue disappears if you stop overloading it for ptrace purposes, which is the clean thing to do in the long run anyway. But there are subtler issues that haven't yet directly affected ptrace. In this scenario, the event has already happened and that's externally visible (the child exists). (In the equivalent case for exec, you can tell from /proc/pid/exe, the effects of setuid have happened, etc.) We don't have the option of saying that the group-stop happened first. If that were so, this event would not have happened yet, but it's already been both reported via utrace and become observable by userland. So it should appear as if the other thread started its group-stop after we were already in TASK_TRACED. There is no need or benefit I see in any substantive change to the utrace API reflecting this. It's just that group-stop is an event that can happen after other events, like syscall-exit is. In other versions of this race, we'll already be in utrace_stop() or on the way to it, and hit "we must participate in the bookkeeping." But the bookkeeping is not really enough. In the case where we were the last thread we do set SIGNAL_STOP_STOPPED, but we swallow the parent's notification. Of course you don't notice this in ptrace since it swallows that notification anyway (and since this is a rare race). But for the general case of utrace, it's wrong as it is. So utrace_stop() ought to do the parent notification in this case. That is, the whole middle part of the do_signal_stop() and tracehook_notify_jctl() logic. i.e., utrace_report_jctl() and then both set ->exit_code and call do_notify_parent_cldstop(), modulo ptrace interference. Hmm, perhaps ->exit_code is only ever set now because of ptrace, at least since your task_stopped_code() changes? Perhaps we should just nix setting it in do_signal_stop() too (after new ptrace). Now, back to your case, a different ordering of that same race. There is nothing really wrong with having utrace's hook be before the group_stop_count check in get_signal_to_deliver(). But that would require changing the tracehook interface there, and the existing tracehook_get_signal() seems about as clean as we can make it. It seems fine to me that we get into do_signal_stop(). If we got into utrace_get_signal()->utrace_stop() first, it would just be the case above where we are acting like do_signal_stop() ran anyway. We can change tracehook_notify_jctl() to call utrace_report_jctl() for any nonzero utrace_flags, and check UTRACE_EVENT(JCTL) inside. (Really it could check (UTRACE_EVENT(JCTL) | ENGINE_STOP), but that's an internal bit that only utrace.c itself knows about.) If (after the report_jctl pass if any) anybody wants UTRACE_STOP, then we handle it with utrace_stop() right there (for what==CLD_STOPPED only). That handles the pending group_stop_count by the (fixed) logic above, so that when we come back out from TASK_TRACED (assuming no unrelated new stops) group_stop_count==0 and do_signal_stop() falls through its no-op case. For that plan, we have to give utrace_report_jctl() a return value that tracehook_notify_jctl() passes back so it can return 0 when utrace_stop() ran (and did any notification itself). But I think that flies, is perhaps moderately clean, and does not need any changes outside tracehook/utrace. What do you think? Thanks, Roland From roland at redhat.com Fri Sep 18 09:50:40 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 18 Sep 2009 02:50:40 -0700 (PDT) Subject: [PATCH 38] make sure PTRACE_CONT "disables" SYSCALL_EXIT report In-Reply-To: Jan Kratochvil's message of Friday, 18 September 2009 11:14:00 +0200 <20090918091359.GA11742@host0.dyn.jankratochvil.net> References: <20090915184901.GA2398@redhat.com> <20090917221724.D06E970@magilla.sf.frob.com> <20090918091359.GA11742@host0.dyn.jankratochvil.net> Message-ID: <20090918095040.EE416278F@magilla.sf.frob.com> > With current utrace it is no longer a fulltime assignment so it is OK this way. Thanks for tending the suite, it's been very helpful. Roland From oleg at redhat.com Fri Sep 18 17:40:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Sep 2009 19:40:35 +0200 Subject: [PATCH 33] implement stacked stop events In-Reply-To: <20090914171904.CBB6495@magilla.sf.frob.com> References: <20090914060633.GA8446@redhat.com> <20090914083251.BB2E073F8@magilla.sf.frob.com> <20090914101836.GA26416@redhat.com> <20090914171904.CBB6495@magilla.sf.frob.com> Message-ID: <20090918174035.GA13403@redhat.com> On 09/14, Roland McGrath wrote: > > > Basically, we have ev_push() and ev_pop(), that is all. > > I don't mean it's hard to understand what the code does. > It's clear enough that it's a simple ring buffer scheme. > > But just having that extra data structure is extra complexity and storage > even so. It's quite overly general for what is really needed. First of all, I am not sure we need this abstraction layer too. It was quickly added after a sleepless night when I realized my previous plan was hopelessly wrong. See also the end this email... I'd like to keep it for now, because it is easier to me to change the code this way. For example, ptrace_report_syscall_exit() does not have to know anything about the previous state, it just pushes the new state. And if we should do something on resume I can place the related code close to callback's code, this way it is immediately obvious (to me!) what's going on. The problem is, when I started this work, I knew nothing about what ptrace actually does. I only understood ptrace_stop/signals part. Now I am trying to "clone" the current behaviour looking at the current code, and I never know what I can miss and what should be changed later. > > We need to record the values for task->exit_code and task->ptrace_message > > at least. _Perhaps_, we also need to record the bit from context->options, > > I am not sure. > > Do you really need to store more than one ptrace_message word? I don't > think so. Let's think about the cases. Where is there a "stacked" event > that has a message word? I think that's only PTRACE_EVENT_VFORK_DONE. Again, I am not sure we need more than one ptrace_message word. I just don't know, and I didn't even try to think about this. All I know now, ->ev_message is the simple way to correctly set ->ptrace_message. > Why do you think you might need to record any option bits? > The past state of option bits should not matter. (from [PATCH 37] "introduce ptrace_event->ev_options") > > When the tracee resumes from TASK_TRACED, context->options can be changed. > > > > Introduce ptrace_event->ev_options. If a callback sets ->ev_options != 0, > > do_ptrace_resume() checks that context->options matches or discards the > > event. > > IMHO this hair is a pretty clear indication that the "queued reports" model > is just not the right model. You have all this new complexity because of > the model that you queue the details of the report at event time, but in > reality much of that determination belongs at report time rather than event > time. Agreed. (and I thought about this too even before I added ->ev_array). But again, this way ptrace_resume() becomes very simple, it knows nothing about the event. All logic lives near the callback's code. And. Currently I am not 100% sure we can always figure out the next state during resume (if it wasn't recorded previously like this model does). > But I think you need to answer my earlier question about the motivation for > this whole plan. Once the code will work (or "mostly" work), and once I will be able to actually understand what I am trying to implement, I am going to remove this layer. Because yes, I think most probably you are right, the reality is simpler. (however: _perhaps_ jctl stops can add some complications, not sure). Perhaps I am wrong, but I think it is much simpler to simplify the working code, compared to improving/complicating the code which doesn't work. So, in short: ->ev_array was added just to make some progress. Not sure this was the wise choice though. Oleg. From oleg at redhat.com Fri Sep 18 18:43:29 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Sep 2009 20:43:29 +0200 Subject: [PATCH 39] make sure PTRACE_SYSCALL reports SYSCALL_EXIT In-Reply-To: <20090917222651.717B870@magilla.sf.frob.com> References: <20090915184903.GA2401@redhat.com> <20090917222651.717B870@magilla.sf.frob.com> Message-ID: <20090918184329.GB13403@redhat.com> On 09/17, Roland McGrath wrote: > > > If the tracee enters PTRACE_EVENT_EXEC stop without TIF_SYSCALL_TRACE > > and then the tracer does ptrace(PTRACE_SYSCALL), we should report > > SYSCALL_EXIT event. > > Indeed. But note that without PTRACE_O_TRACEEXEC, we do not have an "event > stop", but just send ourselves a normal signal. Yes, > In that case, a > PTRACE_SYSCALL resuming from the entry stop for execve will hit the exit > stop first (just like any other syscall), and then dequeue the signal. Confused... Do you think something is wrong with the current code? Yes, without PTRACE_O_TRACEEXEC ptrace_report_exec() doesn't push the event, it sends SIGTRAP to itself. This signal will be reported after SYSCALL_EXIT (if we were resumed by PTRACE_SYSCALL after SYSCAL_ENTRY). IOW, I assume this test-case int main(void) { int pid, stat; pid = fork(); if (!pid) { assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); execl("/bin/true", "true", NULL); assert(0); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD)); // ----must be exec syscall_entry ------------ assert(0 == ptrace(PTRACE_SYSCALL, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); assert(stat == 0x857F); // ----must be exec syscall_exit -------------- assert(0 == ptrace(PTRACE_SYSCALL, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); assert(stat == 0x857F); // ----must be SIGTRAP ------------------------ assert(0 == ptrace(PTRACE_SYSCALL, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); assert(stat == 0x057F); return 0; } is right, correct? Oleg. From roland at redhat.com Fri Sep 18 20:50:20 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 18 Sep 2009 13:50:20 -0700 (PDT) Subject: [PATCH 39] make sure PTRACE_SYSCALL reports SYSCALL_EXIT In-Reply-To: Oleg Nesterov's message of Friday, 18 September 2009 20:43:29 +0200 <20090918184329.GB13403@redhat.com> References: <20090915184903.GA2401@redhat.com> <20090917222651.717B870@magilla.sf.frob.com> <20090918184329.GB13403@redhat.com> Message-ID: <20090918205020.2582E279E@magilla.sf.frob.com> > Confused... Do you think something is wrong with the current code? No, I was just being explicit about the nonobvious quirks of the semantics. (They merit some comments in the eventual code.) > IOW, I assume this test-case [...] > is right, correct? Yes. Thanks, Roland From roland at redhat.com Fri Sep 18 21:02:53 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 18 Sep 2009 14:02:53 -0700 (PDT) Subject: [PATCH 33] implement stacked stop events In-Reply-To: Oleg Nesterov's message of Friday, 18 September 2009 19:40:35 +0200 <20090918174035.GA13403@redhat.com> References: <20090914060633.GA8446@redhat.com> <20090914083251.BB2E073F8@magilla.sf.frob.com> <20090914101836.GA26416@redhat.com> <20090914171904.CBB6495@magilla.sf.frob.com> <20090918174035.GA13403@redhat.com> Message-ID: <20090918210253.A625989@magilla.sf.frob.com> > Once the code will work (or "mostly" work), and once I will be able to > actually understand what I am trying to implement, I am going to remove > this layer. Because yes, I think most probably you are right, the reality > is simpler. (however: _perhaps_ jctl stops can add some complications, > not sure). Sure, that is fine. I didn't have a fully correct implementation before, so I don't claim to be sure about what holes might be in what I've considered. I'm just sure we can find and consider all the underlying complexities together so we become sure what is really required. > Perhaps I am wrong, but I think it is much simpler to simplify the working > code, compared to improving/complicating the code which doesn't work. Well, sure, except perhaps when the "easy to understand" path to "working" gets hairier and hairier with new caveats introduced by the abstraction. > So, in short: ->ev_array was added just to make some progress. Not sure > this was the wise choice though. Understood. My chief metric remains "overall progress" and so whatever works best for you is the way to go about it. The flurry of hairy patches just got me suspicious of whether this path was really the efficient one for you, but it's up to you. Thanks, Roland From mldireto at tudoemoferta.com.br Fri Sep 18 23:11:50 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Fri, 18 Sep 2009 20:11:50 -0300 Subject: Central de Alarme Agility Auto-Instalavel Message-ID: An HTML attachment was scrubbed... URL: From gypsophila at cegelec.com Sat Sep 19 17:23:36 2009 From: gypsophila at cegelec.com (Matthias Fleming) Date: Sat, 19 Sep 2009 09:23:36 -0800 Subject: Want her to make all your dreams come true in bed? Message-ID: <20090919092336.5020308@cegelec.com> Best price level ever - do not hesitate to contact us! http://gphs.worthythus.com/ From senderpromo at gmail.com Wed Sep 16 03:01:51 2009 From: senderpromo at gmail.com (Mundial 2010) Date: Wed, 16 Sep 2009 05:01:51 +0200 Subject: Equipe-se para apoiar Portugal no Euro 2010 Message-ID: Portugal vai ao Mundial 2010? Equipe-se para o Mundial: http://promoportugal.com/iemailer/link.php?M=584113&N=28&L=13&F=T -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Sep 21 02:53:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 21 Sep 2009 04:53:35 +0200 Subject: Q: what user_enable_single_step() actually means? Message-ID: <20090921025335.GA13423@redhat.com> Help! I spent all Sunday trying to do something with PTRACE_SINGLESTEP. And I am totally confused, to the point I don't even know how/what to ask. OK. Please forget about utrace. The tracee sleeps in, say, ptrace_signal()-> ptrace_stop() path. The tracer does ptrace(PTRACE_SINGLESTEP, data => 0). How this works? I thought that the following happens: - PTRACE_SINGLESTEP does user_enable_single_step() - when the tracee returns to user mode, the next instruction causes exception, do_debug()->send_sigtrap() sends SIGTRAP - the tracee notices the signal and reports this SIGTRAP But, whatever I did this doesn't work. So, what user_enable_single_step() actually means? Finally I modified sys_prctl, --- kernel/sys.c~ 2009-07-13 17:44:27.000000000 +0200 +++ kernel/sys.c 2009-09-21 04:01:06.000000000 +0200 @@ -1428,6 +1428,10 @@ SYSCALL_DEFINE5(prctl, int, option, unsi error = 0; switch (option) { + case 666: + user_enable_single_step(current); + break; + case PR_SET_PDEATHSIG: if (!valid_signal(arg2)) { error = -EINVAL; Doesn't work. I mean, do_debug() is not called after return from prctl(666). I tried task_pt_regs(current)->flags |= X86_EFLAGS_TF; instead of user_enable_single_step(), this doesn't work too. Perhaps there is some magic with syscall/sysret? Damn! I failed to google the low-level description of these instructions. Does sysret restore flags? At least. Is it true that X86_EFLAGS_TF should provoke the exception/do_debug? Otherwise, what triggers do_debug()->send_sigtrap() ? Oh. I guess I should read some intel docs, but I don't know where to start. Oleg. From roland at redhat.com Mon Sep 21 05:13:52 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 20 Sep 2009 22:13:52 -0700 (PDT) Subject: Q: what user_enable_single_step() actually means? In-Reply-To: Oleg Nesterov's message of Monday, 21 September 2009 04:53:35 +0200 <20090921025335.GA13423@redhat.com> References: <20090921025335.GA13423@redhat.com> Message-ID: <20090921051352.319BAB1@magilla.sf.frob.com> > - PTRACE_SINGLESTEP does user_enable_single_step() > > - when the tracee returns to user mode, the next instruction > causes exception, do_debug()->send_sigtrap() sends SIGTRAP > > - the tracee notices the signal and reports this SIGTRAP Correct. But if the tracee is inside the syscall path at the time, then it's a little different. TIF_SINGLESTEP being set means it will go to the syscall_trace_leave path and send a signal before it actually returns to user mode. The next time around, when "returns to user mode" really means the final signals-check-and-return-user path, it will indeed be the hardware TF exception firing after a user instruction. (We do this since for the syscall instruction itself, any hardware TF there might have been wasn't helpful--we want to send SIGTRAP when the user's system call has finished, not when the hardware user->kernel entry has finished.) > But, whatever I did this doesn't work. So, what user_enable_single_step() > actually means? It works very well in the vanilla kernel, so you can always go back to that and start poking things to watch it happening. (Just for good measure, I did boot vanilla v2.6.31-6618-gebc79c4 and verify that e.g. ptrace-tests tests/step-simple does still work. I don't think anything about this stuff has changed recently.) > I tried > > task_pt_regs(current)->flags |= X86_EFLAGS_TF; > > instead of user_enable_single_step(), this doesn't work too. It's great to get to understand this level of stuff, but really you should not have to for the work you are doing now. The existing arch layer should work for you just the same as it works in the vanilla kernel today. If it doesn't, I can probably be the one to worry about how it needs to be fixed. I tried your prctl hack on the vanilla kernel and a test program does indeed get a SIGTRAP. (This is an x86_64 kernel on an Intel chip, trying both 32-bit and 64-bit test programs.) > Perhaps there is some magic with syscall/sysret? Damn! I failed to google > the low-level description of these instructions. Does sysret restore flags? There is lots of magic. :-) Yes, sysret restores flags, though sysexit does not (and that's what 32-bit tasks on Intel chips use--so the sysexit code paths restore flags directly with popf). But there are two more things about that (and that's not even to go into syscall or sysenter on 32-bit kernels!). First, when syscall exits do set TF that is only to cause a trap after the *next* user instruction. To simulate the hardware effect of TF across the syscall instruction (i.e. for "stepi" over "syscall", "sysenter", or "int $0x80" to stop right after that instruction itself), we have TIF_SINGLESTEP. Second, lots of things lead you to actually take the "iret" return path instead, and that is what always happens in ptrace situations in practice. If you're either in the handle_signal path, or in the syscall_trace_leave path, then you're always going to wind up taking the iret path (and there are lots of other causes to wind up on that path). > At least. Is it true that X86_EFLAGS_TF should provoke the exception/do_debug? Yes. You can even set it yourself in userland with: pushf orl $0x100, (%rsp) /* or (%esp) */ popf and see the signal. The hardware feature is that when TF is set, the completion of an instruction generates the trap (do_debug path). (There are magic caveats like "popf" setting TF makes it apply to the next instruction's completion rather than to the completion of "popf".) > Otherwise, what triggers do_debug()->send_sigtrap() ? > > Oh. I guess I should read some intel docs, but I don't know where to start. http://www.intel.com/products/processor/manuals/index.htm You can also (at least in the US, don't know about EU), request free printed versions of the same manuals they have there in PDF, which I like to have. (Though they add new things more often than I want new printed manuals.) Thanks, Roland From divulgacao at refrimur.com Mon Sep 21 05:28:33 2009 From: divulgacao at refrimur.com (Refrimur) Date: Mon, 21 Sep 2009 02:28:33 -0300 Subject: REFRIMUR SETEMBRO 2009 Message-ID: An HTML attachment was scrubbed... URL: From bjorn at darbeirut.com Mon Sep 21 16:39:46 2009 From: bjorn at darbeirut.com (Betty Leon) Date: Mon, 21 Sep 2009 17:39:46 +0100 Subject: Huge male pipe, permanent reult Message-ID: <001f01ca3ad1$bf6120f0$5f2c3e6a@HelmZolieck> Natural large hose maker http://tfisi.xuajfennue.com/ From oleg at redhat.com Mon Sep 21 19:08:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 21 Sep 2009 21:08:36 +0200 Subject: Q: what user_enable_single_step() actually means? In-Reply-To: <20090921051352.319BAB1@magilla.sf.frob.com> References: <20090921025335.GA13423@redhat.com> <20090921051352.319BAB1@magilla.sf.frob.com> Message-ID: <20090921190836.GA27320@redhat.com> Thanks Roland. But now I am even more confused... On 09/20, Roland McGrath wrote: > > > - PTRACE_SINGLESTEP does user_enable_single_step() > > > > - when the tracee returns to user mode, the next instruction > > causes exception, do_debug()->send_sigtrap() sends SIGTRAP > > > > - the tracee notices the signal and reports this SIGTRAP > > Correct. But if the tracee is inside the syscall path at the time, then > it's a little different. TIF_SINGLESTEP being set means it will go to the > syscall_trace_leave path and send a signal before it actually returns to > user mode. I am not sure... I can hardly read entry_64.S, but I am not sure system_call_fastpath: path calls syscall_trace_leave() on exit... OK, I added printk to syscall_trace_leave(), please see below. > > At least. Is it true that X86_EFLAGS_TF should provoke the exception/do_debug? > > Yes. You can even set it yourself in userland with: > > pushf > orl $0x100, (%rsp) /* or (%esp) */ > popf > > and see the signal. Yes, this works. > > But, whatever I did this doesn't work. So, what user_enable_single_step() > > actually means? > > It works very well in the vanilla kernel > ... > I tried your prctl hack on the vanilla kernel and a test program does > indeed get a SIGTRAP. (This is an x86_64 kernel on an Intel chip, trying > both 32-bit and 64-bit test programs.) I used the vanilla kernel too. It doesn't work for me. Under KVM at least... OK, the kernel patch: --- TTT/kernel/sys.c~TF_FBG 2009-06-17 14:11:26.000000000 +0200 +++ TTT/kernel/sys.c 2009-09-21 20:03:27.000000000 +0200 @@ -1428,6 +1428,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsi error = 0; switch (option) { + case 666: + printk(KERN_INFO "prctl: before=%lX\n", task_pt_regs(current)->flags); + user_enable_single_step(current); + printk(KERN_INFO "prctl: after=%lX\n", task_pt_regs(current)->flags); + break; + case PR_SET_PDEATHSIG: if (!valid_signal(arg2)) { error = -EINVAL; --- TTT/arch/x86/kernel/ptrace.c~TF_FBG 2009-06-11 14:16:46.000000000 +0200 +++ TTT/arch/x86/kernel/ptrace.c 2009-09-21 20:22:52.000000000 +0200 @@ -1520,6 +1520,8 @@ asmregparm long syscall_trace_enter(stru asmregparm void syscall_trace_leave(struct pt_regs *regs) { + printk(KERN_INFO "trace_leave enter\n"); + if (unlikely(current->audit_context)) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); @@ -1543,6 +1545,8 @@ asmregparm void syscall_trace_leave(stru * system call instruction. */ if (test_thread_flag(TIF_SINGLESTEP) && - tracehook_consider_fatal_signal(current, SIGTRAP)) + tracehook_consider_fatal_signal(current, SIGTRAP)) { + printk(KERN_INFO "trace_leave sends SIGTRAP\n"); send_sigtrap(current, regs, 0, TRAP_BRKPT); + } } version: $ uname -a Linux myhost 2.6.31-00008-g41b61a1-dirty #2 SMP PREEMPT Mon Sep 21 20:23:05 CEST 2009 x86_64 QEMU Virtual CPU version 0.9.1 GenuineIntel GNU/Linux The 1ts test: int main(void) { assert(0 == prctl(666)); for (;;) ; return 0; } it doesn't get SIGTRAP, and syscall_trace_leave() is not called. $ dmesg -c prctl: before=10246 prctl: after=10346 The same for this test: int main(void) { assert(0 == prctl(666)); pause(); return 0; } However, int main(void) { assert(0 == prctl(666)); printf("after prctl\n"); return 0; } dies with "Trace/breakpoint trap", dmesg says: prctl: before=10246 prctl: after=10346 trace_leave enter I guess "trace_leave enter" corresponds to the next syscall, not to prtcl(). This test int main(void) { printf("before prctl\n"); assert(0 == prctl(666)); printf("after prctl\n"); return 0; } gets SIGTRAP too, but printf() succeeds: before prctl after prctl Trace/breakpoint trap The final test-case: static inline unsigned long getflags(void) { unsigned long flags; asm volatile("pushf ; pop %0\n" : "=rm" (flags) : /* no input */ : "memory"); return flags; } int main(void) { unsigned long flags; printf("user_enable_single_step()...\n"); assert(0 == prctl(666)); flags = getflags(); printf("flags=%lX\n", flags); for (;;) ; return 0; } Result: user_enable_single_step()... flags=246 Trace/breakpoint trap dmesg is the same: prctl: before=10246 prctl: after=10346 trace_leave enter Oleg. From oleg at redhat.com Mon Sep 21 19:38:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 21 Sep 2009 21:38:43 +0200 Subject: Q: what user_enable_single_step() actually means? In-Reply-To: <20090921190836.GA27320@redhat.com> References: <20090921025335.GA13423@redhat.com> <20090921051352.319BAB1@magilla.sf.frob.com> <20090921190836.GA27320@redhat.com> Message-ID: <20090921193843.GA30781@redhat.com> On 09/21, Oleg Nesterov wrote: > > However, > > int main(void) > { > assert(0 == prctl(666)); > > printf("after prctl\n"); > > return 0; > } > > dies with "Trace/breakpoint trap", dmesg says: > > prctl: before=10246 > prctl: after=10346 > trace_leave enter > > I guess "trace_leave enter" corresponds to the next syscall, not to prtcl(). Yes, I modified the patch a bit (see below) to print the syscall number, now dmesg says: prctl: before=10246 prctl: after=10346 trace_leave enter: ip=7F3A5BEAEBE4 nr=5 send_sigtrap: ip=7F3A5BEAEBEA __NR_fstat == 5 > This test > > int main(void) > { > printf("before prctl\n"); > > assert(0 == prctl(666)); > > printf("after prctl\n"); > > return 0; > } > > gets SIGTRAP too, but printf() succeeds: > > before prctl > after prctl > Trace/breakpoint trap Indeed, now send_sigtrap() is called after sys_write(), prctl: before=10246 prctl: after=10346 trace_leave enter: ip=7FA34D5EF8F0 nr=1 send_sigtrap: ip=7FA34D5EF8F6 __NR_write == 1. Looks like, ptrace can't rely on user_enable_single_step(), unless the syscall was entered with _TIF_SYSCALL_TRACE/_TIF_SINGLESTEP or we are going to return with signal. Confused, confused, confused. Oleg. From oleg at redhat.com Mon Sep 21 20:27:47 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 21 Sep 2009 22:27:47 +0200 Subject: Q: what user_enable_single_step() actually means? In-Reply-To: <20090921193843.GA30781@redhat.com> References: <20090921025335.GA13423@redhat.com> <20090921051352.319BAB1@magilla.sf.frob.com> <20090921190836.GA27320@redhat.com> <20090921193843.GA30781@redhat.com> Message-ID: <20090921202747.GA825@redhat.com> On 09/21, Oleg Nesterov wrote: > > Yes, I modified the patch a bit (see below) to print the syscall number, Forgot to attach the patch. I guess it is not really needed, but just in case. Oleg. --- TTT/kernel/sys.c~TF_FBG 2009-06-17 14:11:26.000000000 +0200 +++ TTT/kernel/sys.c 2009-09-21 20:03:27.000000000 +0200 @@ -1428,6 +1428,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsi error = 0; switch (option) { + case 666: + printk(KERN_INFO "prctl: before=%lX\n", task_pt_regs(current)->flags); + user_enable_single_step(current); + printk(KERN_INFO "prctl: after=%lX\n", task_pt_regs(current)->flags); + break; + case PR_SET_PDEATHSIG: if (!valid_signal(arg2)) { error = -EINVAL; --- TTT/arch/x86/kernel/ptrace.c~TF_FBG 2009-06-11 14:16:46.000000000 +0200 +++ TTT/arch/x86/kernel/ptrace.c 2009-09-21 21:18:00.000000000 +0200 @@ -1446,6 +1446,8 @@ void send_sigtrap(struct task_struct *ts { struct siginfo info; + printk(KERN_INFO "send_sigtrap: ip=%lX\n", regs->ip); + tsk->thread.trap_no = 1; tsk->thread.error_code = error_code; @@ -1520,6 +1522,8 @@ asmregparm long syscall_trace_enter(stru asmregparm void syscall_trace_leave(struct pt_regs *regs) { + printk(KERN_INFO "trace_leave enter: ip=%lX nr=%ld\n", regs->ip, regs->orig_ax); + if (unlikely(current->audit_context)) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); @@ -1543,6 +1547,8 @@ asmregparm void syscall_trace_leave(stru * system call instruction. */ if (test_thread_flag(TIF_SINGLESTEP) && - tracehook_consider_fatal_signal(current, SIGTRAP)) + tracehook_consider_fatal_signal(current, SIGTRAP)) { + printk(KERN_INFO "trace_leave sends SIGTRAP\n"); send_sigtrap(current, regs, 0, TRAP_BRKPT); + } } From oleg at redhat.com Mon Sep 21 21:07:15 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 21 Sep 2009 23:07:15 +0200 Subject: Q: what user_enable_single_step() actually means? In-Reply-To: <20090921193843.GA30781@redhat.com> References: <20090921025335.GA13423@redhat.com> <20090921051352.319BAB1@magilla.sf.frob.com> <20090921190836.GA27320@redhat.com> <20090921193843.GA30781@redhat.com> Message-ID: <20090921210715.GA4551@redhat.com> On 09/21, Oleg Nesterov wrote: > > Looks like, ptrace can't rely on user_enable_single_step(), unless the syscall > was entered with _TIF_SYSCALL_TRACE/_TIF_SINGLESTEP or we are going to return > with signal. And there is another issue: finish_resume_report(UTRACE_RESUME) does user_disable_single_step(). Now I _hope_ I fully understand why my initial patch to handle PTRACE_SINGLESTEP didn't work. report_signal/quiesce should re-assert SINGLESTEP, it should be recorded in ptrace_context. With the test patch below on top of "[PATCH 50] ptrace_request: use ptrace_lookup_engine()" the kernel passes these tests step-jump-cont step-to-breakpoint step-simple These step-into-handler step-through-sigret fail, but I think this is understandable: ptrace_report_signal() doen't process UTRACE_SIGNAL_HANDLER yet. Now I need to think a bit more before I send the PTRACE_SINGLESTEP changes. And perhaps you can shed more light on enable_disable_single_step() magic... Oleg. --- PU/kernel/utrace.c~TF_FBG 2009-09-15 10:34:59.000000000 +0200 +++ PU/kernel/utrace.c 2009-09-21 22:42:15.000000000 +0200 @@ -1765,7 +1765,7 @@ static void finish_resume_report(struct case UTRACE_REPORT: case UTRACE_RESUME: default: - user_disable_single_step(task); + //user_disable_single_step(task); break; } } --- PU/kernel/ptrace.c~51_STEP_SIMPLE 2009-09-17 21:03:11.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-21 19:52:55.000000000 +0200 @@ -924,6 +924,7 @@ static void ptrace_wake_up(struct utrace static void do_ptrace_resume(struct utrace_engine *engine, struct task_struct *tracee, + enum utrace_resume_action action, long request, long data) { struct ptrace_context *context = ptrace_context(engine); @@ -950,7 +951,7 @@ static void do_ptrace_resume(struct utra } } - ptrace_wake_up(engine, tracee, UTRACE_RESUME); + ptrace_wake_up(engine, tracee, action); } static int ptrace_resume(struct utrace_engine *engine, @@ -992,7 +993,7 @@ static int ptrace_resume(struct utrace_e } if (!ret) - do_ptrace_resume(engine, child, request, data); + do_ptrace_resume(engine, child, action, request, data); return ret; } From info at soft-direct.net Tue Sep 22 11:49:34 2009 From: info at soft-direct.net (Formation Management) Date: Tue, 22 Sep 2009 14:49:34 +0300 Subject: =?utf-8?q?Devenez_un_leader_n=C3=A9=2C_offre_sp=C3=A9ciale_!?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Sep 23 00:26:25 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 23 Sep 2009 02:26:25 +0200 Subject: [PATCH 51-52] stepping Message-ID: <20090923002625.GA31543@redhat.com> Implement PTRACE_SINGLESTEP/PTRACE_SINGLEBLOCK. As usual, this needs further cleanups, but I hope the code is more or less correct. Oleg. From oleg at redhat.com Wed Sep 23 00:26:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 23 Sep 2009 02:26:27 +0200 Subject: [PATCH 51] implement PTRACE_SINGLESTEP/PTRACE_SINGLEBLOCK Message-ID: <20090923002627.GA31551@redhat.com> Change ptrace_resume() path to pass the correct "action" argument to utrace_control(), the current code always uses UTRACE_RESUME while PTRACE_SINGLEXXX needs UTRACE_XXXSTEP. Introduce ptrace_context->resume to remember this action, we have to re-assert it from report_quiesce/report_signal callbacks. The next patch changes ptrace_report_signal(UTRACE_SIGNAL_HANDLER). --- kernel/ptrace.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) --- PU/kernel/ptrace.c~51_STEP_SIMPLE 2009-09-17 21:03:11.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-23 00:50:28.000000000 +0200 @@ -25,7 +25,7 @@ #include typedef void (*resume_func_t)(struct utrace_engine *, - struct task_struct*, long); + struct task_struct*, long); struct ptrace_event { int ev_code; @@ -42,6 +42,8 @@ struct ptrace_context { struct ptrace_event ev_array[2]; unsigned int ev_first, ev_last; + + enum utrace_resume_action resume; }; static inline bool ev_empty(struct ptrace_context *context) @@ -348,6 +350,7 @@ static u32 ptrace_report_signal(u32 acti struct k_sigaction *return_ka) { struct ptrace_context *context = ptrace_context(engine); + enum utrace_resume_action resume = context->resume; struct ptrace_event *ev; if (!ev_empty(context)) { @@ -362,27 +365,27 @@ static u32 ptrace_report_signal(u32 acti WARN_ON(1); case UTRACE_SIGNAL_REPORT: if (!context->siginfo) - return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + return resume | UTRACE_SIGNAL_IGN; if (WARN_ON(context->siginfo != info)) - return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + return resume | UTRACE_SIGNAL_IGN; context->siginfo = NULL; if (!info->si_signo) // debugger cancelled sig - return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + return resume | UTRACE_SIGNAL_IGN; /* * If the (new) signal is now blocked, requeue it. */ if (sigismember(&task->blocked, info->si_signo)) { send_sig_info(info->si_signo, info, task); - return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + return resume | UTRACE_SIGNAL_IGN; } spin_lock_irq(&task->sighand->siglock); *return_ka = task->sighand->action[info->si_signo - 1]; spin_unlock_irq(&task->sighand->siglock); - return UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; + return resume | UTRACE_SIGNAL_DELIVER; default: WARN_ON(context->siginfo); @@ -411,7 +414,7 @@ static u32 ptrace_report_quiesce(u32 act return UTRACE_STOP; } - return UTRACE_RESUME; + return event ? UTRACE_RESUME : context->resume; } static void ptrace_release(void *data) @@ -463,6 +466,8 @@ static int ptrace_attach_task(struct tas if (unlikely(!context)) return -ENOMEM; + context->resume = UTRACE_RESUME; + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, @@ -924,6 +929,7 @@ static void ptrace_wake_up(struct utrace static void do_ptrace_resume(struct utrace_engine *engine, struct task_struct *tracee, + enum utrace_resume_action action, long request, long data) { struct ptrace_context *context = ptrace_context(engine); @@ -950,7 +956,8 @@ static void do_ptrace_resume(struct utra } } - ptrace_wake_up(engine, tracee, UTRACE_RESUME); + context->resume = action; + ptrace_wake_up(engine, tracee, action); } static int ptrace_resume(struct utrace_engine *engine, @@ -992,7 +999,7 @@ static int ptrace_resume(struct utrace_e } if (!ret) - do_ptrace_resume(engine, child, request, data); + do_ptrace_resume(engine, child, action, request, data); return ret; } From oleg at redhat.com Wed Sep 23 00:26:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 23 Sep 2009 02:26:31 +0200 Subject: [PATCH 52] implement UTRACE_SIGNAL_HANDLER stepping Message-ID: <20090923002631.GA31554@redhat.com> Change ptrace_report_signal() to handle UTRACE_SIGNAL_HANDLER case correctly: just push the new stop event if the tracer wants stepping. We do not set context->siginfo = info, this would be wrong because we do not report a signal. I wonder how the tracer can distinguish this case from the real SIGTRAP. >From now, compared to the vanilla kernel, we fail 2 tests: attach-wait-on-stopped - this is correct, it should fail, ptrace_detach() doesn't do the unconditional wakeup. attach-into-signal - this is understandable. This test assumes that after ptrace(DETACH, sig) the next attach should not see this signal. I wonder if we should try hard to keep this behaviour, this doesn't look very useful to me. This is sad, because this just means we don't have enough tests... --- kernel/ptrace.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) --- PU/kernel/ptrace.c~52_SIGNAL_HANDLER 2009-09-23 00:50:28.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-23 01:46:48.000000000 +0200 @@ -362,7 +362,16 @@ static u32 ptrace_report_signal(u32 acti switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: - WARN_ON(1); + if (resume != UTRACE_RESUME) { + if (WARN_ON(context->siginfo)) + context->siginfo = NULL; + + ev = ev_push(context); + ev->ev_code = SIGTRAP; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; + } + case UTRACE_SIGNAL_REPORT: if (!context->siginfo) return resume | UTRACE_SIGNAL_IGN; From roland at redhat.com Wed Sep 23 00:36:54 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 22 Sep 2009 17:36:54 -0700 (PDT) Subject: Q: what user_enable_single_step() actually means? In-Reply-To: Oleg Nesterov's message of Monday, 21 September 2009 21:08:36 +0200 <20090921190836.GA27320@redhat.com> References: <20090921025335.GA13423@redhat.com> <20090921051352.319BAB1@magilla.sf.frob.com> <20090921190836.GA27320@redhat.com> Message-ID: <20090923003654.EA6EB13F37@magilla.sf.frob.com> > Thanks Roland. > > But now I am even more confused... I get that combination a lot! ;-) Just to keep everyone confused, note that this thread now has approximately nothing to do with single-step. It really does have something to do with single-step, but only in the special sense of TIF_SINGLESTEP handling syscall exit, which is at low-level really more of a syscall-tracing situation than it is a single-step situation. It actually took me writing this paragraph to remember that this did have anything to do with single-step! > I am not sure... I can hardly read entry_64.S, but I am not sure > system_call_fastpath: path calls syscall_trace_leave() on exit... There are various paths to flag checks that cover TIF_SYSCALL_TRACE and TIF_SINGLESTEP (_TIF_WORK_SYSCALL_EXIT). But you are right, there is one path that skips that. I believe this can come up for vanilla ptrace only in one situation, and that case should probably be considered a bug. If you entered the syscall with TIF_SYSCALL_TRACE, then you wind up taking the int_ret_from_sys_call path out. In almost all the other cases that ptrace can see, you will wind up taking that path out too for other reasons. I think the only cases where you can have a ptrace stop followed by actually taking the ret_from_sys_call path are tracehook_report_clone stops (i.e. the stop inside a clone/fork/vfork syscall). If you last used PTRACE_CONT or whatever and then hit PTRACE_EVENT_FORK et al, resuming with PTRACE_SYSCALL will fail to hit the syscall-exit report for that fork/clone syscall. I added ptrace-tests/tests/syscall-from-clone.c for this case. As I thought from inspection, it fails on x86-64 but not on a 32-bit process. I'm also pretty sure (without having tested it) that it doesn't fail on a 32-bit kernel. It would be worthwhile to cons a version of this test case that uses PTRACE_SINGLESTEP instead of PTRACE_SYSCALL. I think your situation is tickling the same issue, but we should have an empirical test. > I used the vanilla kernel too. It doesn't work for me. Under KVM at least... I make no claims about KVM. It has not lacked for obscure bugs in the past. If the results are ever confusing, you should certainly compare the behavior of virtual and real machines to verify before you let it drive you insane. In this case, of course, it's just squirrely little assembly paths driving you insane, but, trust me, you'd feel robbed if you went this insane just because of a KVM bug! :-D I have a fix in hand that I'll send upstream before too long. But perhaps it should wait for the PTRACE_SINGLESTEP version of the test case. git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-roland.git branch x86/ptrace-syscall-exit > And there is another issue: finish_resume_report(UTRACE_RESUME) does > user_disable_single_step(). That is a separate issue, which is simply understanding the utrace API. The x86-64 bug above is real but unrelated. > Now I _hope_ I fully understand why my initial patch to handle > PTRACE_SINGLESTEP didn't work. report_signal/quiesce should re-assert > SINGLESTEP, it should be recorded in ptrace_context. Yes. That's largely what ptrace_set_action() et al was all about. Thanks, Roland From roland at redhat.com Wed Sep 23 00:51:13 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 22 Sep 2009 17:51:13 -0700 (PDT) Subject: [PATCH 52] implement UTRACE_SIGNAL_HANDLER stepping In-Reply-To: Oleg Nesterov's message of Wednesday, 23 September 2009 02:26:31 +0200 <20090923002631.GA31554@redhat.com> References: <20090923002631.GA31554@redhat.com> Message-ID: <20090923005113.8464213F37@magilla.sf.frob.com> > We do not set context->siginfo = info, this would be wrong because > we do not report a signal. I wonder how the tracer can distinguish > this case from the real SIGTRAP. Just like other ptrace_notify() cases, only by checking details like .si_code=0 vs known TRAP_* values that a real hardware-generated SIGTRAP gives you. > This is sad, because this just means we don't have enough tests... You're a man who likes a challenge! ;-) Thanks, Roland From info at canal-direct.com Wed Sep 23 08:00:18 2009 From: info at canal-direct.com (=?ISO-8859-1?Q?Canal_Direct?=) Date: Wed, 23 Sep 2009 10:00:18 +0200 Subject: =?iso-8859-1?q?Livraison_sp=E9ciale_pour_votre_soci=E9t=E9?= Message-ID: An HTML attachment was scrubbed... URL: From srikar at linux.vnet.ibm.com Wed Sep 23 10:17:25 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 23 Sep 2009 15:47:25 +0530 Subject: [PATCH 0/2] Code cleanup patches. Message-ID: <20090923101725.11304.57534.sendpatchset@srdronam.in.ibm.com> This patchset just does code cleanup and no additional bugfixes or features. After applying this patchset, checkpatch reports: total: 0 errors, 0 warnings, 0 checks, 1560 lines checked Subject: [PATCH 0/2] Code cleanup patches. File: /tmp/gdbstub-patches/4/intro Subject: [PATCH 1/2] Make gdbstub as per coding guidelines. File: /tmp/gdbstub-patches/4/1.patch Subject: [PATCH 2/2] use reusable functions wherever possible. File: /tmp/gdbstub-patches/4/2.patch From srikar at linux.vnet.ibm.com Wed Sep 23 10:17:45 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 23 Sep 2009 15:47:45 +0530 Subject: [PATCH 2/2] use reusable functions wherever possible. In-Reply-To: <20090923101725.11304.57534.sendpatchset@srdronam.in.ibm.com> References: <20090923101725.11304.57534.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090923101745.11304.8717.sendpatchset@srdronam.in.ibm.com> Remove duplicate code where possible by using reusable functions. Signed-off-by: Srikar Dronamraju --- kernel/utrace-gdb.c | 272 +++++++++++++++++++++++---------------------------- 1 files changed, 123 insertions(+), 149 deletions(-) diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index f44b3c0..97811c2 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -793,6 +793,84 @@ static int gdb_remote_register_info(struct gdb_connection *p, return -ENOENT; } +static inline int fetch_remote_register_info(struct gdb_connection *p, + struct task_struct *task, + int index, + unsigned *pos, + unsigned *count, + unsigned *bytes) +{ + int rsn; + + rsn = gdb_remote_register_info(p, task, index, pos, count, bytes); + pr_debug("gdb register %u => rsn %d p%u c%u b%u\n", index, rsn, + *pos, *count, *bytes); + if (rsn > 0) { + /* + * If we want to extract register data, make sure we're + * fetching at least that much. + */ + BUG_ON(*count > 0 && *count < *bytes); + /* Assert reg_contents size is right. */ + BUG_ON(MAX_REG_WIDTH < *bytes || MAX_REG_WIDTH < *count); + } + return rsn; +} + +static inline int get_set_regset_view(struct task_struct *task, + unsigned pos, unsigned count, + unsigned char *reg_contents, + int rsn, bool set) +{ + int rc; + const struct user_regset_view *rsv; + const struct user_regset *rs; + + if (!count) { + if (!set) + memset(reg_contents, 0, MAX_REG_WIDTH); + return 0; + } + + /* real register */ + if (set) + BUG_ON(count > MAX_REG_WIDTH); + + rsv = task_user_regset_view(task); + BUG_ON(rsn >= rsv->n); + rs = &rsv->regsets[rsn]; + + /* Extract the register values into reg_contents[]. */ + if (set) + rc = (rs->set)(task, rs, pos, count, reg_contents, NULL); + else + rc = (rs->get)(task, rs, pos, count, reg_contents, NULL); + + return rc; +} + +static inline void prepare_regset_set(struct gdb_connection *p, + unsigned char *reg_contents, + size_t *start, unsigned bytes) +{ + int j; + + /* + * 0-fill the register copy. + * XXX initialize it from rs->get() instead? + */ + memset(reg_contents, 0, MAX_REG_WIDTH); + + /* + * Hex-unconvert all the bytes. + * XXX: endianness adjust for count != bytes + */ + for (j = 0; j < bytes; j++) + reg_contents[j] = byteme(p->input_buf[*start + 2 * j], + p->input_buf[*start + 2 * j + 1]); + *start += 2 * bytes; +} + /* * Process an entire, checksum-confirmed $command# at the front of * p->input_buf[]. The input and output mutexes are being held. @@ -880,50 +958,23 @@ static void handle_gdb_command_packet(struct gdb_connection *p, unsigned rs_count; unsigned rs_pos; unsigned bytes; - const struct user_regset_view *rsv; - const struct user_regset *rs; + int rsn; unsigned char reg_contents[MAX_REG_WIDTH]; - int rsn = gdb_remote_register_info(p, task, i, - &rs_pos, &rs_count, - &bytes); - + rsn = fetch_remote_register_info(p, task, i, + &rs_pos, &rs_count, &bytes); if (rsn < 0) break; - /* - * If we want to extract register data, make sure - * we're fetching at least that much. - */ - BUG_ON(rs_count > 0 && rs_count < bytes); - /* Assert reg_contents size is right. */ - BUG_ON(sizeof(reg_contents) < bytes || - sizeof(reg_contents) < rs_count); - - if (rs_count) { /* real register */ - rsv = task_user_regset_view(task); - BUG_ON(rsn >= rsv->n); - rs = &rsv->regsets[rsn]; - - /* - * Extract the register values into - * reg_contents[]. - */ - rc = (rs->get)(task, rs, rs_pos, rs_count, - reg_contents, NULL); - if (rc) - break; - - } else { /* dummy value */ - memset(reg_contents, 0, sizeof(reg_contents)); - } + rc = get_set_regset_view(task, rs_pos, rs_count, + reg_contents, rsn, false); + if (rc) + break; /* * Hex-dump it. * XXX: endianness adjust for count != bytes */ - /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u (", - i, rsn, rs_pos, rs_count, bytes); */ for (j = 0; j < bytes; j++) { /* pr_debug("%02x", reg_contents[j]); */ push_output_hex(p, reg_contents[j]); @@ -937,66 +988,27 @@ static void handle_gdb_command_packet(struct gdb_connection *p, i = 0; op_start = 2; /* use as input pointer, past $G in command */ while (p->input_buf[op_start] != '#' && - op_start < p->input_buf_size) { + op_start < p->input_buf_size) { unsigned rs_count; unsigned rs_pos; unsigned bytes; - const struct user_regset_view *rsv; - const struct user_regset *rs; + int rsn; unsigned char reg_contents[MAX_REG_WIDTH]; - int rsn = gdb_remote_register_info(p, task, i, - &rs_pos, &rs_count, - &bytes); - /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u\n", - i, rsn, rs_pos, rs_count, bytes); */ - + rsn = fetch_remote_register_info(p, task, i, + &rs_pos, &rs_count, &bytes); if (rsn < 0) break; - /* - * If we want to extract register data, make sure - * we're fetching at least that much. - */ - BUG_ON(rs_count > 0 && rs_count < bytes); - /* Assert reg_contents size is right. */ - BUG_ON(sizeof(reg_contents) < bytes || - sizeof(reg_contents) < rs_count); - /* Remaining packet too short? */ if ((op_start + 2 * bytes + 3) < p->input_buf_size) break; - /* - * 0-fill the register copy. XXX initialize - * it from rs->get() instead? - */ - memset(reg_contents, 0, sizeof(reg_contents)); - - /* - * Hex-unconvert all the bytes. - * XXX: endianness adjust for count != bytes - */ - for (j = 0; j < bytes; j++) - reg_contents[j] = - byteme(p->input_buf[op_start + 2 * j], - p->input_buf[op_start + 2 * j + 1]); - op_start += 2 * bytes; - - if (rs_count) { /* real register */ - BUG_ON(rs_count > sizeof(reg_contents)); - rsv = task_user_regset_view(task); - BUG_ON(rsn >= rsv->n); - rs = &rsv->regsets[rsn]; - - /* Set register values from reg_contents[]. */ - rc = (rs->set) (task, rs, rs_pos, rs_count, - reg_contents, NULL); - if (rc) - break; - } else { /* dummy register */ - ; - } + prepare_regset_set(p, reg_contents, &op_start, bytes); + rc = get_set_regset_view(task, rs_pos, rs_count, + reg_contents, rsn, true); + if (rc) + break; } if (p->input_buf[op_start] == '#' && rc == 0) push_output_packet(p, "OK"); @@ -1017,59 +1029,22 @@ static void handle_gdb_command_packet(struct gdb_connection *p, unsigned rs_count; unsigned rs_pos; unsigned bytes; - const struct user_regset_view *rsv; - const struct user_regset *rs; + int rsn; unsigned char reg_contents[MAX_REG_WIDTH]; - int rsn = gdb_remote_register_info(p, task, arg1, - &rs_pos, &rs_count, - &bytes); - pr_debug("gdb register %lu => rsn %d p%u c%u b%u\n", - arg1, rsn, rs_pos, rs_count, bytes); - + rsn = fetch_remote_register_info(p, task, arg1, + &rs_pos, &rs_count, &bytes); if (rsn < 0) break; - /* - * If we want to extract register data, make sure - * we're fetching at least that much. - */ - BUG_ON(rs_count > 0 && rs_count < bytes); - /* Assert reg_contents size is right. */ - BUG_ON(sizeof(reg_contents) < bytes || - sizeof(reg_contents) < rs_count); - /* Remaining packet too short? */ if ((op_start + 2 * bytes + 3) < p->input_buf_size) break; - /* - * 0-fill the register copy. - * XXX initialize it from rs->get() instead? - */ - memset(reg_contents, 0, sizeof(reg_contents)); - - /* - * Hex-unconvert all the bytes. - * XXX: endianness adjust for count != bytes - */ - for (j = 0; j < bytes; j++) - reg_contents[j] = - byteme(p->input_buf[op_start + 2 * j], - p->input_buf[op_start + 2 * j + 1]); - op_start += 2 * bytes; - - if (rs_count) { /* real register */ - BUG_ON(rs_count > sizeof(reg_contents)); - rsv = task_user_regset_view(task); - BUG_ON(rsn >= rsv->n); - rs = &rsv->regsets[rsn]; - - /* Set register values from reg_contents[]. */ - rc = (rs->set) (task, rs, rs_pos, rs_count, - reg_contents, NULL); - WARN_ON(rc); - } + prepare_regset_set(p, reg_contents, &op_start, bytes); + rc = get_set_regset_view(task, rs_pos, rs_count, + reg_contents, rsn, true); + WARN_ON(rc); if (p->input_buf[op_start] == '#' && rc == 0) push_output_packet(p, "OK"); else @@ -1238,7 +1213,8 @@ static int proc_gdb_open(struct inode *inode, struct file *filp) mutex_lock(&gdb_connections_mutex); - /* Reject if a connection exists for the thread group + /* + * Reject if a connection exists for the thread group * leader. */ list_for_each_entry(p, &gdb_connections, link) { @@ -1519,29 +1495,27 @@ again: } else if (p->input_buf[0] == '$') { /* command packet */ int j; unsigned char checksum = 0; + unsigned char checksum2; for (j = 1; j < p->input_buf_size - 2; j++) { - if (p->input_buf[j] == '#') { - unsigned char checksum2; - checksum2 = byteme(p->input_buf[j + 1], - p->input_buf[j + 2]); - pr_debug("received gdb packet %.*s\n", - j + 3, &p->input_buf[0]); - if (checksum == checksum2) { - push_output(p, '+'); - handle_gdb_command_packet(p, - task); - } else { - push_output(p, '-'); - } - /* Consume the whole packet. */ - p->input_buf_size -= (j + 3); - memmove(&p->input_buf[0], - &p->input_buf[j + 3], - p->input_buf_size); - break; - } else { + if (p->input_buf[j] != '#') { checksum += p->input_buf[j]; + continue; } + checksum2 = byteme(p->input_buf[j + 1], + p->input_buf[j + 2]); + pr_debug("received gdb packet %.*s\n", + j + 3, &p->input_buf[0]); + if (checksum == checksum2) { + push_output(p, '+'); + handle_gdb_command_packet(p, task); + } else + push_output(p, '-'); + + /* Consume the whole packet. */ + p->input_buf_size -= (j + 3); + memmove(&p->input_buf[0], &p->input_buf[j + 3], + p->input_buf_size); + break; } /* End searching for end of packet */ /* @@ -1556,8 +1530,8 @@ again: * we'll iterate one more time in this loop. */ } else { /* junk character */ - printk(KERN_WARNING "Unexpected character (%x) received" - " on /proc/%d/gdb connection.\n", + printk(KERN_WARNING "Unexpected character (%x) " + "received on /proc/%d/gdb connection.\n", (int)p->input_buf[0], task_pid_nr(task)); /* Consume the input. */ memmove(&p->input_buf[0], &p->input_buf[1], From srikar at linux.vnet.ibm.com Wed Sep 23 10:17:35 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Wed, 23 Sep 2009 15:47:35 +0530 Subject: [PATCH 1/2] Make gdbstub as per coding guidelines. In-Reply-To: <20090923101725.11304.57534.sendpatchset@srdronam.in.ibm.com> References: <20090923101725.11304.57534.sendpatchset@srdronam.in.ibm.com> Message-ID: <20090923101735.11304.33856.sendpatchset@srdronam.in.ibm.com> Make gdbstub code more clean (as per LKML coding guidelines) This patch has most whitespace changes than actual changes. Also comment style has been changed where necessary. Signed-off-by: Srikar Dronamraju --- kernel/utrace-gdb.c | 2151 +++++++++++++++++++++++++-------------------------- 1 files changed, 1072 insertions(+), 1079 deletions(-) diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c index f8a07af..f44b3c0 100644 --- a/kernel/utrace-gdb.c +++ b/kernel/utrace-gdb.c @@ -10,7 +10,7 @@ * Red Hat Author: Frank Ch. Eigler */ -/* +/* * TODO list: * * floating-point register bank support for g/G/P/etc. packets @@ -21,7 +21,7 @@ #define DEBUG 1 #include -#include +#include #include #include #include @@ -39,32 +39,34 @@ #include #endif - -/** struct gdb_connection - Tracks one active gdb-process session. +/* + * struct gdb_connection - Tracks one active gdb-process session. */ #define GDB_BUFMAX 4096 +#define MAX_REG_WIDTH 16 /* Maximum Register Width */ #ifdef CONFIG_HAVE_UPROBES struct gdb_uprobe { - struct uprobe up; - struct list_head link; - int disarmed_p; + struct uprobe up; + struct list_head link; + int disarmed_p; }; #endif - struct gdb_connection { - pid_t target; - struct utrace_engine *engine; + pid_t target; + struct utrace_engine *engine; - /* changed under output_mutex */ - int at_quiesce_do; - unsigned char stopcode[GDB_BUFMAX]; // set <=> at_quiesce_do = UTRACE_STOP - int pass_signals; - int stop_signals; - /* XXX: per-thread later */ + /* changed under output_mutex */ + int at_quiesce_do; + + /* set <=> at_quiesce_do = UTRACE_STOP */ + unsigned char stopcode[GDB_BUFMAX]; + int pass_signals; + int stop_signals; + /* XXX: per-thread later */ #ifdef CONFIG_HAVE_UPROBES /* @@ -75,170 +77,170 @@ struct gdb_connection { * caching the gdb_uprobe pointer. */ struct gdb_uprobe *current_gdb_uprobe; /* XXX: per-thread later */ - struct list_head uprobes; + struct list_head uprobes; #endif - char output_buf[GDB_BUFMAX]; - size_t output_buf_size; - loff_t output_buf_read; - struct mutex output_mutex; - wait_queue_head_t output_wait; + char output_buf[GDB_BUFMAX]; + size_t output_buf_size; + loff_t output_buf_read; - char input_buf[GDB_BUFMAX]; - size_t input_buf_size; - struct mutex input_mutex; - wait_queue_head_t input_wait; + /* Protects output_buf, at_quiesce_do */ + struct mutex output_mutex; + wait_queue_head_t output_wait; - struct list_head link; -}; + char input_buf[GDB_BUFMAX]; + size_t input_buf_size; + /* Protects input_buf. */ + struct mutex input_mutex; + wait_queue_head_t input_wait; + + struct list_head link; +}; static LIST_HEAD(gdb_connections); static DEFINE_MUTEX(gdb_connections_mutex); static const struct utrace_engine_ops gdb_utrace_ops; - /* ------------------------------------------------------------------------ */ - -/* Map from kernel-side signal numbers (include/asm/signal.h) to gdb - remote protocol signal numbers (include/gdb/signals.h). */ - +/* + * Map from kernel-side signal numbers (include/asm/signal.h) to gdb + * remote protocol signal numbers (include/gdb/signals.h). + */ unsigned gdb_signal_map[] = { - [SIGHUP]=1, - [SIGINT]=2, - [SIGQUIT]=3, - [SIGILL]=4, - [SIGTRAP]=5, - [SIGABRT]=6, - [SIGBUS]=10, - [SIGFPE]=8, - [SIGKILL]=9, - [SIGUSR1]=30, - [SIGSEGV]=11, - [SIGUSR2]=31, - [SIGPIPE]=13, - [SIGALRM]=14, - [SIGTERM]=15, - [SIGCHLD]=20, - [SIGCONT]=19, - [SIGSTOP]=17, - [SIGTSTP]=18, - [SIGTTIN]=21, - [SIGTTOU]=22, - [SIGURG]=16, - [SIGXCPU]=24, - [SIGXFSZ]=25, - [SIGVTALRM]=26, - [SIGPROF]=27, - [SIGWINCH]=28, - [SIGIO]=23, - [SIGPWR]=32, - [SIGSYS]=12, + [SIGHUP] = 1, + [SIGINT] = 2, + [SIGQUIT] = 3, + [SIGILL] = 4, + [SIGTRAP] = 5, + [SIGABRT] = 6, + [SIGBUS] = 10, + [SIGFPE] = 8, + [SIGKILL] = 9, + [SIGUSR1] = 30, + [SIGSEGV] = 11, + [SIGUSR2] = 31, + [SIGPIPE] = 13, + [SIGALRM] = 14, + [SIGTERM] = 15, + [SIGCHLD] = 20, + [SIGCONT] = 19, + [SIGSTOP] = 17, + [SIGTSTP] = 18, + [SIGTTIN] = 21, + [SIGTTOU] = 22, + [SIGURG] = 16, + [SIGXCPU] = 24, + [SIGXFSZ] = 25, + [SIGVTALRM] = 26, + [SIGPROF] = 27, + [SIGWINCH] = 28, + [SIGIO] = 23, + [SIGPWR] = 32, + [SIGSYS] = 12, }; - -/* Map the incoming signo to TARGET_SIGNAL_foo, if possible. If not, - * pass it through. +/* + * Map the incoming signo to TARGET_SIGNAL_foo, if possible. If not, + * pass it through. */ -static unsigned map_signal_kern2gdb (unsigned kernel_signo) +static unsigned map_signal_kern2gdb(unsigned kernel_signo) { - if (kernel_signo < sizeof(gdb_signal_map)/sizeof(unsigned)) - return gdb_signal_map[kernel_signo] ?: kernel_signo; - return kernel_signo; + if (kernel_signo < sizeof(gdb_signal_map) / sizeof(unsigned)) + return gdb_signal_map[kernel_signo] ? : kernel_signo; + return kernel_signo; } -static unsigned map_signal_gdb2kern (unsigned gdb_signo) +static unsigned map_signal_gdb2kern(unsigned gdb_signo) { - unsigned i; - for (i=0; ioutput_buf_size; + size_t start = p->output_buf_size; - BUG_ON (p->output_buf_size + 1 >= GDB_BUFMAX); - p->output_buf[p->output_buf_size++] = '$'; - return start; + BUG_ON(p->output_buf_size + 1 >= GDB_BUFMAX); + p->output_buf[p->output_buf_size++] = '$'; + return start; } - /* Add a character to the output queue. Assumes output_mutex held. */ -static void push_output (struct gdb_connection *p, unsigned char c) +static void push_output(struct gdb_connection *p, unsigned char c) { - /* We know some space must exist; we check for this in - proc_gdb_write() for example. */ - BUG_ON (p->output_buf_size >= GDB_BUFMAX); - p->output_buf[p->output_buf_size++] = c; + /* + * We know some space must exist; we check for this in + * proc_gdb_write() for example. + */ + BUG_ON(p->output_buf_size >= GDB_BUFMAX); + p->output_buf[p->output_buf_size++] = c; } - -static char hex[] = "0123456789abcdef"; /* Lower case use due to http://sourceware.org/bugzilla/show_bug.cgi?id=9665 */ - +static char hex[] = "0123456789abcdef"; /* Add a byte (hexified) to the output queue. Assumes output_mutex held. */ -static void push_output_hex (struct gdb_connection *p, unsigned char c) +static void push_output_hex(struct gdb_connection *p, unsigned char c) { - /* We know some space must exist; we check for this in - proc_gdb_write() for example. */ - BUG_ON (p->output_buf_size >= GDB_BUFMAX); - p->output_buf[p->output_buf_size++] = hex[(c & 0xf0) >> 4]; - p->output_buf[p->output_buf_size++] = hex[(c & 0x0f) >> 0]; + /* + * We know some space must exist; we check for this in + * proc_gdb_write() for example. + */ + BUG_ON(p->output_buf_size >= GDB_BUFMAX); + p->output_buf[p->output_buf_size++] = hex[(c & 0xf0) >> 4]; + p->output_buf[p->output_buf_size++] = hex[(c & 0x0f) >> 0]; } - -/* Finish the last packet. Starting after the given '$' offset, compute - * the checksum and append it. */ -static void push_output_packet_end (struct gdb_connection *p, size_t start) +/* + * Finish the last packet. Starting after the given '$' offset, compute + * the checksum and append it. + */ +static void push_output_packet_end(struct gdb_connection *p, size_t start) { - unsigned char checksum = 0; - int i; + unsigned char checksum = 0; + int i; - BUG_ON (p->output_buf_size + 3 >= GDB_BUFMAX); - BUG_ON (p->output_buf[start] != '$'); + BUG_ON(p->output_buf_size + 3 >= GDB_BUFMAX); + BUG_ON(p->output_buf[start] != '$'); - for (i=start+1; ioutput_buf_size; i++) - checksum += p->output_buf[i]; + for (i = start + 1; i < p->output_buf_size; i++) + checksum += p->output_buf[i]; - p->output_buf[p->output_buf_size++] = '#'; - p->output_buf[p->output_buf_size++] = hex[(checksum & 0xf0) >> 4]; - p->output_buf[p->output_buf_size++] = hex[(checksum & 0x0f) >> 0]; + p->output_buf[p->output_buf_size++] = '#'; + p->output_buf[p->output_buf_size++] = hex[(checksum & 0xf0) >> 4]; + p->output_buf[p->output_buf_size++] = hex[(checksum & 0x0f) >> 0]; } - /* Add a complete packet payload to the output queue. */ -static void push_output_packet (struct gdb_connection *p, const char *s) +static void push_output_packet(struct gdb_connection *p, const char *s) { - size_t ss = strlen(s); - size_t start; - int i; - - start = push_output_packet_start(p); - for (i=0; icurrent_gdb_uprobe = gup; } -void gdb_register_complete(struct uprobe *up, int regflag, int ret) +/* + * uprobes callback to signify the completion of registration + * formalities. This gets called iff the register_uprobe() reported + * EINPROGRESS. (To signify registration of a probe was called from a + * uprobe callback, or when the traced thread was stopped) + * + */ +static void gdb_register_complete(struct uprobe *up, int regflag, int ret) { - if (regflag) { /* register_uprobe */ + if (regflag) { /* register_uprobe */ struct gdb_uprobe *gup; - struct gdb_connection *gp = NULL, *p = NULL; - - mutex_lock(&gdb_connections_mutex); - list_for_each_entry(p, &gdb_connections, link) { - if (p->target == task_tgid_nr(current)) { - gp = p; - break; - } - } - mutex_unlock(&gdb_connections_mutex); + struct gdb_connection *gc; - if (!gp) + gc = find_gdb_connection(current); + if (!gc) return; gup = container_of(up, struct gdb_uprobe, up); @@ -342,7 +346,26 @@ void gdb_register_complete(struct uprobe *up, int regflag, int ret) /* Dont bother to use a callback for unregister */ up->registration_callback = NULL; INIT_LIST_HEAD(&gup->link); - list_add_tail(&gup->link, &gp->uprobes); + list_add_tail(&gup->link, &gc->uprobes); + } +} + +/* + * gdbstub stopped tracing the process, Lets delete all probes + * inserted by gdbstub. + */ +static inline void gdb_unregister_uprobes(struct gdb_connection *p, + struct task_struct *task) +{ + struct gdb_uprobe *gup, *gup2; + + if (!task) + return; + + list_for_each_entry_safe(gup, gup2, &p->uprobes, link) { + unregister_uprobe(&gup->up); + list_del(&gup->link); + kfree(gup); } } #endif /* CONFIG_HAVE_UPROBES */ @@ -350,80 +373,66 @@ void gdb_register_complete(struct uprobe *up, int regflag, int ret) /* utrace callbacks */ u32 gdb_utrace_report_quiesce(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *task, - unsigned long event) + struct utrace_engine *engine, + struct task_struct *task, unsigned long event) { - struct gdb_connection *p = engine->data; - pr_debug ("report_quiesce %d event 0x%lx 0x%x->0x%x\n", task->pid, - event, action, p->at_quiesce_do); + struct gdb_connection *p = engine->data; - return p->at_quiesce_do; -} + pr_debug("report_quiesce %d event 0x%lx 0x%x->0x%x\n", task->pid, + event, action, p->at_quiesce_do); + return p->at_quiesce_do; +} u32 gdb_utrace_report_clone(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *parent, - unsigned long clone_flags, - struct task_struct *child) + struct utrace_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) { - pr_debug ("report_clone %d->%d\n", parent->pid, child->pid); + pr_debug("report_clone %d->%d\n", parent->pid, child->pid); - if (clone_flags & CLONE_THREAD) { - printk (KERN_WARNING "unsupported multithreading on /proc/%d/gdb.\n", - task_pid_nr (parent)); - } - /* XXX: is there anything else to do here? */ + if (clone_flags & CLONE_THREAD) { + printk(KERN_WARNING + "unsupported multithreading on /proc/%d/gdb.\n", + task_pid_nr(parent)); + } + /* XXX: is there anything else to do here? */ return UTRACE_RESUME; } - u32 gdb_utrace_report_exec(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *task, - const struct linux_binfmt *fmt, - const struct linux_binprm *bprm, - struct pt_regs *regs) + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs) { - /* XXX: Model an exec as if it were an exit. */ - struct gdb_connection *p = engine->data; + /* XXX: Model an exec as if it were an exit. */ + struct gdb_connection *p = engine->data; - pr_debug ("report_exec %d->%s\n", task->pid, task->comm); + pr_debug("report_exec %d->%s\n", task->pid, task->comm); - mutex_lock(&p->output_mutex); + mutex_lock(&p->output_mutex); - p->at_quiesce_do = UTRACE_STOP; - snprintf (p->stopcode, GDB_BUFMAX, "W%02x", 0); - push_output_packet (p, p->stopcode); + p->at_quiesce_do = UTRACE_STOP; + snprintf(p->stopcode, GDB_BUFMAX, "W%02x", 0); + push_output_packet(p, p->stopcode); #ifdef CONFIG_HAVE_UPROBES - { - struct list_head *l; - struct list_head *l2; - list_for_each_safe(l, l2, & p->uprobes) { - struct gdb_uprobe *gup = list_entry(l, - struct gdb_uprobe, link); - unregister_uprobe(&gup->up); - /* - * int rc = unmap_uprobe(& gup->up); - * WARN_ON(rc != 0); - */ - list_del(&gup->link); - kfree(gup); - } - } + gdb_unregister_uprobes(p, task); #endif /* CONFIG_HAVE_UPROBES */ - mutex_unlock(&p->output_mutex); - wake_up(&p->output_wait); + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); - /* Suspend the exec operation, to ensure that the connected gdb - receives the notification packet, and lets us go. */ + /* + * Suspend the exec operation, to ensure that the connected gdb + * receives the notification packet, and lets us go. + */ return UTRACE_STOP; } - u32 gdb_utrace_report_signal(u32 action, struct utrace_engine *engine, struct task_struct *task, @@ -432,18 +441,16 @@ u32 gdb_utrace_report_signal(u32 action, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { - struct gdb_connection *p = engine->data; - u32 ret = action; - int kern_p; - - mutex_lock(&p->output_mutex); + struct gdb_connection *p = engine->data; + u32 ret = action; - kern_p = (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))); + mutex_lock(&p->output_mutex); - pr_debug ("report_signal %d (0x%x) kern %d skip %d stop %d\n", - task->pid, action, kern_p, p->pass_signals, p->stop_signals); + pr_debug("report_signal %d (0x%x) skip %d stop %d\n", + task->pid, action, p->pass_signals, p->stop_signals); - /* The target is about to receive a signal. There are several + /* + * The target is about to receive a signal. There are several * cases: * * 1) This is an ordinary signal. We UTRACE_STOP to notify gdb. @@ -466,15 +473,15 @@ u32 gdb_utrace_report_signal(u32 action, * 5) This is a UTRACE_SIGNAL_HANDLER event. UTRACE_RESUME. */ - switch (utrace_signal_action(action)) { - case UTRACE_SIGNAL_HANDLER: /* case 5 */ - p->at_quiesce_do = UTRACE_RESUME; - ret = UTRACE_RESUME | utrace_signal_action(action); - break; + switch (utrace_signal_action(action)) { + case UTRACE_SIGNAL_HANDLER: /* case 5 */ + p->at_quiesce_do = UTRACE_RESUME; + ret = UTRACE_RESUME | utrace_signal_action(action); + break; case UTRACE_SIGNAL_REPORT: case UTRACE_SIGNAL_DELIVER: - case UTRACE_SIGNAL_IGN: /* XXX: bother notify? */ + case UTRACE_SIGNAL_IGN: /* XXX: bother notify? */ case UTRACE_SIGNAL_TERM: case UTRACE_SIGNAL_CORE: case UTRACE_SIGNAL_STOP: @@ -483,7 +490,7 @@ u32 gdb_utrace_report_signal(u32 action, /* This should be UTRACE_SIGNAL_REPORT */ if (p->stop_signals > 0) { p->stop_signals = 0; - /* Indicate as if thread received a SIGINT*/ + /* Indicate as if thread received a SIGINT */ snprintf(p->stopcode, GDB_BUFMAX, "S%02x", 2); push_output_packet(p, p->stopcode); p->at_quiesce_do = UTRACE_STOP; @@ -529,126 +536,93 @@ u32 gdb_utrace_report_signal(u32 action, } p->current_gdb_uprobe = NULL; break; - } - if (p->pass_signals > 0 /*&& kern_p*/) { /* case 4 */ - p->pass_signals --; - p->at_quiesce_do = UTRACE_RESUME; - ret = UTRACE_RESUME | utrace_signal_action (action); /* deliver */ - } else { /* case 1 */ - snprintf (p->stopcode, GDB_BUFMAX, "S%02x", - map_signal_kern2gdb(info->si_signo)); - push_output_packet (p, p->stopcode); - p->at_quiesce_do = UTRACE_STOP; + } + if (p->pass_signals > 0) { /* case 4 */ + p->pass_signals--; + p->at_quiesce_do = UTRACE_RESUME; + ret = UTRACE_RESUME | utrace_signal_action(action); + } else { /* case 1 */ + snprintf(p->stopcode, GDB_BUFMAX, "S%02x", + map_signal_kern2gdb(info->si_signo)); + push_output_packet(p, p->stopcode); + p->at_quiesce_do = UTRACE_STOP; ret = UTRACE_STOP | utrace_signal_action(action); - } - break; - } + } + break; + } - pr_debug ("action 0x%x\n", ret); + pr_debug("action 0x%x\n", ret); - mutex_unlock(&p->output_mutex); - wake_up(&p->output_wait); + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); - return ret; + return ret; } - u32 gdb_utrace_report_exit(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *task, - long orig_code, long *code) + struct utrace_engine *engine, + struct task_struct *task, + long orig_code, long *code) { - struct gdb_connection *p = engine->data; + struct gdb_connection *p = engine->data; - pr_debug ("report_exit %d (%lx)\n", task->pid, (unsigned long) orig_code); + pr_debug("report_exit %d (%lx)\n", task->pid, orig_code); - mutex_lock(&p->output_mutex); + mutex_lock(&p->output_mutex); - p->at_quiesce_do = UTRACE_STOP; - snprintf (p->stopcode, GDB_BUFMAX, - "W%02x", (unsigned)(orig_code & 0xFF)); - push_output_packet (p, p->stopcode); + p->at_quiesce_do = UTRACE_STOP; + snprintf(p->stopcode, GDB_BUFMAX, + "W%02x", (unsigned)(orig_code & 0xFF)); + push_output_packet(p, p->stopcode); #ifdef CONFIG_HAVE_UPROBES - { - struct list_head *l; - struct list_head *l2; - list_for_each_safe(l, l2, & p->uprobes) { - struct gdb_uprobe *gup = list_entry(l, - struct gdb_uprobe, link); - unregister_uprobe(&gup->up); - /* - * int rc = unmap_uprobe(& gup->up); - * WARN_ON(rc != 0); - */ - list_del(&gup->link); - kfree(gup); - } - } + gdb_unregister_uprobes(p, task); #endif /* CONFIG_HAVE_UPROBES */ - mutex_unlock(&p->output_mutex); - wake_up(&p->output_wait); + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); - /* Suspend the exit operation, to ensure that the connected gdb - receives the notification packet, and lets us go. */ + /* + * Suspend the exit operation, to ensure that the connected gdb + * receives the notification packet, and lets us go. + */ return UTRACE_STOP; } - u32 gdb_utrace_report_death(struct utrace_engine *engine, - struct task_struct *task, - bool group_dead, int signal) + struct task_struct *task, bool group_dead, int signal) { - struct gdb_connection *p = engine->data; + struct gdb_connection *p = engine->data; - pr_debug ("report_death %d (%d)\n", task->pid, signal); + pr_debug("report_death %d (%d)\n", task->pid, signal); - mutex_lock(&p->output_mutex); + mutex_lock(&p->output_mutex); - p->at_quiesce_do = UTRACE_DETACH; - snprintf (p->stopcode, GDB_BUFMAX, "X%2x", (unsigned)(signal & 0xFF)); - push_output_packet (p, p->stopcode); + p->at_quiesce_do = UTRACE_DETACH; + snprintf(p->stopcode, GDB_BUFMAX, "X%2x", (unsigned)(signal & 0xFF)); + push_output_packet(p, p->stopcode); #ifdef CONFIG_HAVE_UPROBES - { - struct list_head *l; - struct list_head *l2; - list_for_each_safe(l, l2, & p->uprobes) { - struct gdb_uprobe *gup = list_entry(l, - struct gdb_uprobe, link); - unregister_uprobe(&gup->up); - /* - * int rc = unmap_uprobe(& gup->up); - * WARN_ON(rc != 0); - */ - list_del(&gup->link); - kfree(gup); - } - } + gdb_unregister_uprobes(p, task); #endif /* CONFIG_HAVE_UPROBES */ - mutex_unlock(&p->output_mutex); - wake_up(&p->output_wait); - + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); return UTRACE_DETACH; } - - static const struct utrace_engine_ops gdb_utrace_ops = { .report_quiesce = gdb_utrace_report_quiesce, .report_signal = gdb_utrace_report_signal, - .report_death = gdb_utrace_report_death, + .report_death = gdb_utrace_report_death, .report_exit = gdb_utrace_report_exit, .report_exec = gdb_utrace_report_exec, .report_clone = gdb_utrace_report_clone, - /* XXX: syscall trapping is also possible. */ + /* XXX: syscall trapping is also possible. */ }; - - -/* XXX: arch-dependent lookup of gdb remote protocol register +/* + * XXX: arch-dependent lookup of gdb remote protocol register * numbering. The register numbers (user-side) & expected sizes come * from gdb's regformats/FOO-linux.dat. The regset (kernel-side) * numbers could come from offsetof/sizeof constructs based upon each @@ -656,509 +630,525 @@ static const struct utrace_engine_ops gdb_utrace_ops = { */ struct gdb_map_regset { - unsigned pos; /* regset offset */ - unsigned count; /* regset byte count */ - unsigned rsn; /* regset number */ - unsigned bytes; /* gdb's view of register width; <= count */ + unsigned pos; /* regset offset */ + unsigned count; /* regset byte count */ + unsigned rsn; /* regset number */ + unsigned bytes; /* gdb's view of register width; <= count */ }; struct gdb_map_regset arch_i386_map_regset[] = { - [0]={ /* eax */ 6*4, 4, NT_PRSTATUS, 4, }, - [1]={ /* ecx */ 1*4, 4, NT_PRSTATUS, 4, }, - [2]={ /* edx */ 2*4, 4, NT_PRSTATUS, 4, }, - [3]={ /* ebx */ 0*4, 4, NT_PRSTATUS, 4, }, - [4]={ /* esp */ 15*4, 4, NT_PRSTATUS, 4, }, - [5]={ /* ebp */ 5*4, 4, NT_PRSTATUS, 4, }, - [6]={ /* esi */ 3*4, 4, NT_PRSTATUS, 4, }, - [7]={ /* edi */ 4*4, 4, NT_PRSTATUS, 4, }, - [8]={ /* eip */ 12*4, 4, NT_PRSTATUS, 4, }, - [9]={ /* eflags */ 14*4, 4, NT_PRSTATUS, 4, }, - [10]={ /* cs */ 13*4, 4, NT_PRSTATUS, 4, }, - [11]={ /* ss */ 16*4, 4, NT_PRSTATUS, 4, }, - [12]={ /* ds */ 7*4, 4, NT_PRSTATUS, 4, }, - [13]={ /* es */ 8*4, 4, NT_PRSTATUS, 4, }, - [14]={ /* fs */ 9*4, 4, NT_PRSTATUS, 4, }, - [15]={ /* gs */ 10*4, 4, NT_PRSTATUS, 4, }, - [16]={ /* st0 */ 0, 0, NT_PRFPREG, 10, }, - [17]={ /* st1 */ 0, 0, NT_PRFPREG, 10, }, - [18]={ /* st2 */ 0, 0, NT_PRFPREG, 10, }, - [19]={ /* st3 */ 0, 0, NT_PRFPREG, 10, }, - [20]={ /* st4 */ 0, 0, NT_PRFPREG, 10, }, - [21]={ /* st5 */ 0, 0, NT_PRFPREG, 10, }, - [22]={ /* st6 */ 0, 0, NT_PRFPREG, 10, }, - [23]={ /* st7 */ 0, 0, NT_PRFPREG, 10, }, - [24]={ /* fctrl */ 0, 0, NT_PRFPREG, 4, }, - [25]={ /* fstat */ 0, 0, NT_PRFPREG, 4, }, - [26]={ /* ftag */ 0, 0, NT_PRFPREG, 4, }, - [27]={ /* fiseg */ 0, 0, NT_PRFPREG, 4, }, - [28]={ /* fioff */ 0, 0, NT_PRFPREG, 4, }, - [29]={ /* foseg */ 0, 0, NT_PRFPREG, 4, }, - [30]={ /* fooff */ 0, 0, NT_PRFPREG, 4, }, - [31]={ /* fop */ 0, 0, NT_PRFPREG, 4, }, - [32]={ /* xmm0 */ 0, 0, NT_PRFPREG, 16, }, - [33]={ /* xmm1 */ 0, 0, NT_PRFPREG, 16, }, - [34]={ /* xmm2 */ 0, 0, NT_PRFPREG, 16, }, - [35]={ /* xmm3 */ 0, 0, NT_PRFPREG, 16, }, - [36]={ /* xmm4 */ 0, 0, NT_PRFPREG, 16, }, - [37]={ /* xmm5 */ 0, 0, NT_PRFPREG, 16, }, - [38]={ /* xmm6 */ 0, 0, NT_PRFPREG, 16, }, - [39]={ /* xmm7 */ 0, 0, NT_PRFPREG, 16, }, - [40]={ /* mxcsr */ 0, 0, NT_PRFPREG, 4, }, - [41]={ /* orig_eax*/ 0, 0, NT_PRSTATUS, 4, }, + [0] = { /* eax */ 6 * 4, 4, NT_PRSTATUS, 4,}, + [1] = { /* ecx */ 1 * 4, 4, NT_PRSTATUS, 4,}, + [2] = { /* edx */ 2 * 4, 4, NT_PRSTATUS, 4,}, + [3] = { /* ebx */ 0 * 4, 4, NT_PRSTATUS, 4,}, + [4] = { /* esp */ 15 * 4, 4, NT_PRSTATUS, 4,}, + [5] = { /* ebp */ 5 * 4, 4, NT_PRSTATUS, 4,}, + [6] = { /* esi */ 3 * 4, 4, NT_PRSTATUS, 4,}, + [7] = { /* edi */ 4 * 4, 4, NT_PRSTATUS, 4,}, + [8] = { /* eip */ 12 * 4, 4, NT_PRSTATUS, 4,}, + [9] = { /* eflags */ 14 * 4, 4, NT_PRSTATUS, 4,}, + [10] = { /* cs */ 13 * 4, 4, NT_PRSTATUS, 4,}, + [11] = { /* ss */ 16 * 4, 4, NT_PRSTATUS, 4,}, + [12] = { /* ds */ 7 * 4, 4, NT_PRSTATUS, 4,}, + [13] = { /* es */ 8 * 4, 4, NT_PRSTATUS, 4,}, + [14] = { /* fs */ 9 * 4, 4, NT_PRSTATUS, 4,}, + [15] = { /* gs */ 10 * 4, 4, NT_PRSTATUS, 4,}, + [16] = { /* st0 */ 0, 0, NT_PRFPREG, 10,}, + [17] = { /* st1 */ 0, 0, NT_PRFPREG, 10,}, + [18] = { /* st2 */ 0, 0, NT_PRFPREG, 10,}, + [19] = { /* st3 */ 0, 0, NT_PRFPREG, 10,}, + [20] = { /* st4 */ 0, 0, NT_PRFPREG, 10,}, + [21] = { /* st5 */ 0, 0, NT_PRFPREG, 10,}, + [22] = { /* st6 */ 0, 0, NT_PRFPREG, 10,}, + [23] = { /* st7 */ 0, 0, NT_PRFPREG, 10,}, + [24] = { /* fctrl */ 0, 0, NT_PRFPREG, 4,}, + [25] = { /* fstat */ 0, 0, NT_PRFPREG, 4,}, + [26] = { /* ftag */ 0, 0, NT_PRFPREG, 4,}, + [27] = { /* fiseg */ 0, 0, NT_PRFPREG, 4,}, + [28] = { /* fioff */ 0, 0, NT_PRFPREG, 4,}, + [29] = { /* foseg */ 0, 0, NT_PRFPREG, 4,}, + [30] = { /* fooff */ 0, 0, NT_PRFPREG, 4,}, + [31] = { /* fop */ 0, 0, NT_PRFPREG, 4,}, + [32] = { /* xmm0 */ 0, 0, NT_PRFPREG, 16,}, + [33] = { /* xmm1 */ 0, 0, NT_PRFPREG, 16,}, + [34] = { /* xmm2 */ 0, 0, NT_PRFPREG, 16,}, + [35] = { /* xmm3 */ 0, 0, NT_PRFPREG, 16,}, + [36] = { /* xmm4 */ 0, 0, NT_PRFPREG, 16,}, + [37] = { /* xmm5 */ 0, 0, NT_PRFPREG, 16,}, + [38] = { /* xmm6 */ 0, 0, NT_PRFPREG, 16,}, + [39] = { /* xmm7 */ 0, 0, NT_PRFPREG, 16,}, + [40] = { /* mxcsr */ 0, 0, NT_PRFPREG, 4,}, + [41] = { /* orig_eax */ 0, 0, NT_PRSTATUS, 4,}, }; - struct gdb_map_regset arch_x86_64_map_regset[] = { - [0]={ /* rax */ 10*8, 8, NT_PRSTATUS, 8, }, - [1]={ /* rbx */ 5*8, 8, NT_PRSTATUS, 8, }, - [2]={ /* rcx */ 11*8, 8, NT_PRSTATUS, 8, }, - [3]={ /* rdx */ 12*8, 8, NT_PRSTATUS, 8, }, - [4]={ /* rsi */ 13*8, 8, NT_PRSTATUS, 8, }, - [5]={ /* rdi */ 14*8, 8, NT_PRSTATUS, 8, }, - [6]={ /* rbp */ 4*8, 8, NT_PRSTATUS, 8, }, - [7]={ /* rsp */ 19*8, 8, NT_PRSTATUS, 8, }, - [8]={ /* r8 */ 9*8, 8, NT_PRSTATUS, 8, }, - [9]={ /* r9 */ 8*8, 8, NT_PRSTATUS, 8, }, - [10]={ /* r10 */ 7*8, 8, NT_PRSTATUS, 8, }, - [11]={ /* r11 */ 6*8, 8, NT_PRSTATUS, 8, }, - [12]={ /* r12 */ 3*8, 8, NT_PRSTATUS, 8, }, - [13]={ /* r13 */ 2*8, 8, NT_PRSTATUS, 8, }, - [14]={ /* r14 */ 1*8, 8, NT_PRSTATUS, 8, }, - [15]={ /* r15 */ 0*8, 8, NT_PRSTATUS, 8, }, - [16]={ /* rip */ 16*8, 8, NT_PRSTATUS, 8, }, - [17]={ /* flags */ 18*8, 8, NT_PRSTATUS, 4, }, - [18]={ /* cs */ 17*8, 8, NT_PRSTATUS, 4, }, - [19]={ /* ss */ 20*8, 8, NT_PRSTATUS, 4, }, - [20]={ /* ds */ 23*8, 8, NT_PRSTATUS, 4, }, - [21]={ /* es */ 24*8, 8, NT_PRSTATUS, 4, }, - [22]={ /* fs */ 25*8, 8, NT_PRSTATUS, 4, }, - [23]={ /* gs */ 26*8, 8, NT_PRSTATUS, 4, }, - [24]={ /* st0 */ 0, 0, NT_PRFPREG, 10, }, - [25]={ /* st1 */ 0, 0, NT_PRFPREG, 10, }, - [26]={ /* st2 */ 0, 0, NT_PRFPREG, 10, }, - [27]={ /* st3 */ 0, 0, NT_PRFPREG, 10, }, - [28]={ /* st4 */ 0, 0, NT_PRFPREG, 10, }, - [29]={ /* st5 */ 0, 0, NT_PRFPREG, 10, }, - [30]={ /* st6 */ 0, 0, NT_PRFPREG, 10, }, - [31]={ /* st7 */ 0, 0, NT_PRFPREG, 10, }, - [32]={ /* fctrl */ 0, 0, NT_PRFPREG, 4, }, - [33]={ /* fstat */ 0, 0, NT_PRFPREG, 4, }, - [34]={ /* ftag */ 0, 0, NT_PRFPREG, 4, }, - [35]={ /* fiseg */ 0, 0, NT_PRFPREG, 4, }, - [36]={ /* fioff */ 0, 0, NT_PRFPREG, 4, }, - [37]={ /* foseg */ 0, 0, NT_PRFPREG, 4, }, - [38]={ /* fooff */ 0, 0, NT_PRFPREG, 4, }, - [39]={ /* fop */ 0, 0, NT_PRFPREG, 4, }, - [40]={ /* xmm0 */ 0, 0, NT_PRFPREG, 16, }, - [41]={ /* xmm1 */ 0, 0, NT_PRFPREG, 16, }, - [42]={ /* xmm2 */ 0, 0, NT_PRFPREG, 16, }, - [43]={ /* xmm3 */ 0, 0, NT_PRFPREG, 16, }, - [44]={ /* xmm4 */ 0, 0, NT_PRFPREG, 16, }, - [45]={ /* xmm5 */ 0, 0, NT_PRFPREG, 16, }, - [46]={ /* xmm6 */ 0, 0, NT_PRFPREG, 16, }, - [47]={ /* xmm7 */ 0, 0, NT_PRFPREG, 16, }, - [48]={ /* xmm8 */ 0, 0, NT_PRFPREG, 16, }, - [49]={ /* xmm9 */ 0, 0, NT_PRFPREG, 16, }, - [50]={ /* xmm10 */ 0, 0, NT_PRFPREG, 16, }, - [51]={ /* xmm11 */ 0, 0, NT_PRFPREG, 16, }, - [52]={ /* xmm12 */ 0, 0, NT_PRFPREG, 16, }, - [53]={ /* xmm13 */ 0, 0, NT_PRFPREG, 16, }, - [54]={ /* xmm14 */ 0, 0, NT_PRFPREG, 16, }, - [55]={ /* xmm15 */ 0, 0, NT_PRFPREG, 16, }, - [56]={ /* mxcsr */ 0, 0, NT_PRFPREG, 4, }, - [57]={ /* orig_rax*/ 15*8, 8, NT_PRSTATUS, 8, }, + [0] = { /* rax */ 10 * 8, 8, NT_PRSTATUS, 8,}, + [1] = { /* rbx */ 5 * 8, 8, NT_PRSTATUS, 8,}, + [2] = { /* rcx */ 11 * 8, 8, NT_PRSTATUS, 8,}, + [3] = { /* rdx */ 12 * 8, 8, NT_PRSTATUS, 8,}, + [4] = { /* rsi */ 13 * 8, 8, NT_PRSTATUS, 8,}, + [5] = { /* rdi */ 14 * 8, 8, NT_PRSTATUS, 8,}, + [6] = { /* rbp */ 4 * 8, 8, NT_PRSTATUS, 8,}, + [7] = { /* rsp */ 19 * 8, 8, NT_PRSTATUS, 8,}, + [8] = { /* r8 */ 9 * 8, 8, NT_PRSTATUS, 8,}, + [9] = { /* r9 */ 8 * 8, 8, NT_PRSTATUS, 8,}, + [10] = { /* r10 */ 7 * 8, 8, NT_PRSTATUS, 8,}, + [11] = { /* r11 */ 6 * 8, 8, NT_PRSTATUS, 8,}, + [12] = { /* r12 */ 3 * 8, 8, NT_PRSTATUS, 8,}, + [13] = { /* r13 */ 2 * 8, 8, NT_PRSTATUS, 8,}, + [14] = { /* r14 */ 1 * 8, 8, NT_PRSTATUS, 8,}, + [15] = { /* r15 */ 0 * 8, 8, NT_PRSTATUS, 8,}, + [16] = { /* rip */ 16 * 8, 8, NT_PRSTATUS, 8,}, + [17] = { /* flags */ 18 * 8, 8, NT_PRSTATUS, 4,}, + [18] = { /* cs */ 17 * 8, 8, NT_PRSTATUS, 4,}, + [19] = { /* ss */ 20 * 8, 8, NT_PRSTATUS, 4,}, + [20] = { /* ds */ 23 * 8, 8, NT_PRSTATUS, 4,}, + [21] = { /* es */ 24 * 8, 8, NT_PRSTATUS, 4,}, + [22] = { /* fs */ 25 * 8, 8, NT_PRSTATUS, 4,}, + [23] = { /* gs */ 26 * 8, 8, NT_PRSTATUS, 4,}, + [24] = { /* st0 */ 0, 0, NT_PRFPREG, 10,}, + [25] = { /* st1 */ 0, 0, NT_PRFPREG, 10,}, + [26] = { /* st2 */ 0, 0, NT_PRFPREG, 10,}, + [27] = { /* st3 */ 0, 0, NT_PRFPREG, 10,}, + [28] = { /* st4 */ 0, 0, NT_PRFPREG, 10,}, + [29] = { /* st5 */ 0, 0, NT_PRFPREG, 10,}, + [30] = { /* st6 */ 0, 0, NT_PRFPREG, 10,}, + [31] = { /* st7 */ 0, 0, NT_PRFPREG, 10,}, + [32] = { /* fctrl */ 0, 0, NT_PRFPREG, 4,}, + [33] = { /* fstat */ 0, 0, NT_PRFPREG, 4,}, + [34] = { /* ftag */ 0, 0, NT_PRFPREG, 4,}, + [35] = { /* fiseg */ 0, 0, NT_PRFPREG, 4,}, + [36] = { /* fioff */ 0, 0, NT_PRFPREG, 4,}, + [37] = { /* foseg */ 0, 0, NT_PRFPREG, 4,}, + [38] = { /* fooff */ 0, 0, NT_PRFPREG, 4,}, + [39] = { /* fop */ 0, 0, NT_PRFPREG, 4,}, + [40] = { /* xmm0 */ 0, 0, NT_PRFPREG, 16,}, + [41] = { /* xmm1 */ 0, 0, NT_PRFPREG, 16,}, + [42] = { /* xmm2 */ 0, 0, NT_PRFPREG, 16,}, + [43] = { /* xmm3 */ 0, 0, NT_PRFPREG, 16,}, + [44] = { /* xmm4 */ 0, 0, NT_PRFPREG, 16,}, + [45] = { /* xmm5 */ 0, 0, NT_PRFPREG, 16,}, + [46] = { /* xmm6 */ 0, 0, NT_PRFPREG, 16,}, + [47] = { /* xmm7 */ 0, 0, NT_PRFPREG, 16,}, + [48] = { /* xmm8 */ 0, 0, NT_PRFPREG, 16,}, + [49] = { /* xmm9 */ 0, 0, NT_PRFPREG, 16,}, + [50] = { /* xmm10 */ 0, 0, NT_PRFPREG, 16,}, + [51] = { /* xmm11 */ 0, 0, NT_PRFPREG, 16,}, + [52] = { /* xmm12 */ 0, 0, NT_PRFPREG, 16,}, + [53] = { /* xmm13 */ 0, 0, NT_PRFPREG, 16,}, + [54] = { /* xmm14 */ 0, 0, NT_PRFPREG, 16,}, + [55] = { /* xmm15 */ 0, 0, NT_PRFPREG, 16,}, + [56] = { /* mxcsr */ 0, 0, NT_PRFPREG, 4,}, + [57] = { /* orig_rax */ 15 * 8, 8, NT_PRSTATUS, 8,}, }; - - static int gdb_remote_register_info(struct gdb_connection *p, - struct task_struct *task, - unsigned number, - unsigned *pos, unsigned *count, - unsigned *bytes) + struct task_struct *task, + unsigned number, + unsigned *pos, unsigned *count, + unsigned *bytes) { - const struct user_regset_view *rs = task_user_regset_view(task); - int rsn = -1; + const struct user_regset_view *rs = task_user_regset_view(task); + int rsn = -1; - if(rs == 0) - return -ENOENT; - - /* pr_debug ("gdb_remote_register_info rs=%p rs->n=%u\n", rs, rs->n); */ + if (rs == 0) + return -ENOENT; #define GMRSIZE (sizeof(struct gdb_map_regset)) - if(rs->e_machine == EM_386) { - if (number < sizeof(arch_i386_map_regset)/GMRSIZE) { - *pos = arch_i386_map_regset[number].pos; - *count = arch_i386_map_regset[number].count; - *bytes = arch_i386_map_regset[number].bytes; - rsn = arch_i386_map_regset[number].rsn; - } - } else if(rs->e_machine == EM_X86_64) { - if (number < sizeof(arch_x86_64_map_regset)/GMRSIZE) { - *pos = arch_x86_64_map_regset[number].pos; - *count = arch_x86_64_map_regset[number].count; - *bytes = arch_x86_64_map_regset[number].bytes; - rsn = arch_x86_64_map_regset[number].rsn; - } - } /* else ... rsn stays -1. */ - + if (rs->e_machine == EM_386) { + if (number < sizeof(arch_i386_map_regset) / GMRSIZE) { + *pos = arch_i386_map_regset[number].pos; + *count = arch_i386_map_regset[number].count; + *bytes = arch_i386_map_regset[number].bytes; + rsn = arch_i386_map_regset[number].rsn; + } + } else if (rs->e_machine == EM_X86_64) { + if (number < sizeof(arch_x86_64_map_regset) / GMRSIZE) { + *pos = arch_x86_64_map_regset[number].pos; + *count = arch_x86_64_map_regset[number].count; + *bytes = arch_x86_64_map_regset[number].bytes; + rsn = arch_x86_64_map_regset[number].rsn; + } + } + /* else ... rsn stays -1. */ #undef GMRSIZE - /* Now map to the per-architecture regset index, based on the - elf core_note_type we found. */ - if (rsn >= 0) { - unsigned j; - for(j=0; jn; j++) { - if(rs->regsets[j].core_note_type == rsn) - return j; - } - } - - /* Invalid machines, register numbers, rsns, or unset rsns all - * fall through here. - */ - return -ENOENT; -} - - + /* + * Now map to the per-architecture regset index, based on the + * elf core_note_type we found. + */ + if (rsn >= 0) { + unsigned j; + for (j = 0; j < rs->n; j++) { + if (rs->regsets[j].core_note_type == rsn) + return j; + } + } + /* + * Invalid machines, register numbers, rsns, or unset rsns all + * fall through here. + */ + return -ENOENT; +} -/* Process an entire, checksum-confirmed $command# at the front of +/* + * Process an entire, checksum-confirmed $command# at the front of * p->input_buf[]. The input and output mutexes are being held. */ -static void handle_gdb_command_packet (struct gdb_connection *p, struct task_struct *task) +static void handle_gdb_command_packet(struct gdb_connection *p, + struct task_struct *task) { - unsigned long arg1, arg2, arg3; - size_t op_start; - int rc = 0; - int i, j; - - pr_debug ("gdb packet code %c\n", p->input_buf[1]); - - switch (p->input_buf[1]) { - case '?': - if (p->at_quiesce_do != UTRACE_STOP) { - /* shouldn't happen */ - p->stop_signals ++; - rc = utrace_control (task, p->engine, UTRACE_INTERRUPT); - if (rc == -EINPROGRESS) - rc = utrace_barrier(task, p->engine); - /* Note that we don't enqueue a reply packet here, - but make gdb wait for a response from the - utrace report_FOO callbacks. */ - } else { - push_output_packet (p, p->stopcode); - } - break; - - case 'i': /* [ADDR[,NNN]] */ - case 's': /* [ADDR] */ - /* XXX: if !arch_has_single_step() ... then what? */ - case 'c': /* [ADDR] */ - rc = sscanf(& p->input_buf[2], "%lx,%lx", &arg1, &arg2); - if (rc >= 1) { /* Have a PC? */ - /* XXX: set it */ - } - if (rc >= 2) { /* ,NNN present */ - /* XXX: disregard it. */ - } - /* XXX: args ignored */ - p->stopcode[0]='\0'; - p->at_quiesce_do = - ((p->input_buf[1]=='c' || !arch_has_single_step()) - ? UTRACE_RESUME : UTRACE_SINGLESTEP); - if (p->at_quiesce_do == UTRACE_SINGLESTEP) - p->stop_signals ++; - rc = utrace_control (task, p->engine, p->at_quiesce_do); - if (rc == -EINPROGRESS) - rc = utrace_barrier(task, p->engine); - break; - case 'C': /* SIG[;ADDR] */ - case 'S': /* SIG[;ADDR] */ - /* XXX: if !arch_has_single_step() ... then what? */ - case 'I': /* SIG[;ADDR[,NNN?]] */ - rc = sscanf(& p->input_buf[2], "%lx;%lx,%lx", &arg1, &arg2, &arg3); - if (rc >= 1) { /* SIG present */ - send_sig (map_signal_gdb2kern(arg1), task, 1); - } - if (rc >= 2) { /* ;ADDR present */ - /* XXX: not done */ - } - if (rc >= 3) { /* ,NNN present */ - /* XXX: disregard it. */ - } - p->pass_signals ++; - p->stopcode[0]='\0'; - p->at_quiesce_do = - ((p->input_buf[1]=='C' || !arch_has_single_step()) - ? UTRACE_RESUME : UTRACE_SINGLESTEP); - if (p->at_quiesce_do == UTRACE_SINGLESTEP) - p->stop_signals ++; - rc = utrace_control (task, p->engine, p->at_quiesce_do); - if (rc == -EINPROGRESS) - rc = utrace_barrier(task, p->engine); - /* Response will come at next report_signal. */ - break; - case 'D': - push_output_packet (p, "OK"); - /* NB: the .release fop callback performs actual utrace detach. */ - break; - case 'g': - op_start = push_output_packet_start(p); - /* GDB_BUFMAX stands for some random large number, - * known to be larger than the number of gdb indexed - * registers. */ - for (i=0; i 0 && rs_count < bytes); - /* Assert reg_contents size is right. */ - BUG_ON(sizeof(reg_contents) < bytes || - sizeof(reg_contents) < rs_count); - - if (rs_count) { /* real register */ - rsv = task_user_regset_view(task); - BUG_ON(rsn >= rsv->n); - rs = & rsv->regsets[rsn]; - - /* Extract the register value into reg_contents[]. */ - rc = (rs->get) (task, rs, rs_pos, rs_count, - reg_contents, NULL); - if (rc) - break; - } else { /* dummy value */ - memset (reg_contents, 0, sizeof(reg_contents)); - } - - /* Hex-dump it. */ - /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u (", - i, rsn, rs_pos, rs_count, bytes); */ - /* XXX: endianness adjust for count != bytes */ - for(j=0; jinput_buf[op_start] != '#' && - op_start < p->input_buf_size) { - unsigned rs_count; - unsigned rs_pos; - unsigned bytes; - const struct user_regset_view* rsv; - const struct user_regset* rs; - unsigned char reg_contents[16]; /* maximum reg. width */ - - int rsn = gdb_remote_register_info(p, task, i, - &rs_pos, &rs_count, - &bytes); - /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u\n", - i, rsn, rs_pos, rs_count, bytes); */ - - if (rsn < 0) - break; - - /* If we want to extract register data, make sure - we're fetching at least that much. */ - BUG_ON(rs_count > 0 && rs_count < bytes); - /* Assert reg_contents size is right. */ - BUG_ON(sizeof(reg_contents) < bytes || - sizeof(reg_contents) < rs_count); - - /* Remaining packet too short? */ - if ((op_start + 2*bytes + 3) < p->input_buf_size) - break; - - /* 0-fill the register copy. XXX initialize - * it from rs->get() instead? - */ - memset (reg_contents, 0, sizeof(reg_contents)); - - /* Hex-unconvert all the bytes. */ - /* XXX: endianness adjust for count != bytes */ - for(j=0; jinput_buf[op_start+2*j], - p->input_buf[op_start+2*j+1]); - op_start += 2*bytes; - - if (rs_count) { /* real register */ - BUG_ON(rs_count > sizeof(reg_contents)); - rsv = task_user_regset_view(task); - BUG_ON(rsn >= rsv->n); - rs = & rsv->regsets[rsn]; - - /* Set the register value from reg_contents[]. */ - rc = (rs->set) (task, rs, rs_pos, rs_count, - reg_contents, NULL); - if (rc) - break; - } else { /* dummy register */ - ; - } - } - if (p->input_buf[op_start] == '#' && rc == 0) - push_output_packet (p, "OK"); - else - push_output_packet (p, "E01"); - break; - case 'p': /* REG */ - push_output_packet (p, "E01"); - break; - case 'P': /* REG=VAL */ - /* `i' will index p->input_buf to consume VAL hex bytes. */ - rc = sscanf(& p->input_buf[2], "%lx=%n", &arg1, &i); - op_start = i + 2; /* Skip the leading $P also */ - if (rc != 1) { - push_output_packet(p, "E01"); - } else { - unsigned rs_count; - unsigned rs_pos; - unsigned bytes; - const struct user_regset_view* rsv; - const struct user_regset* rs; - unsigned char reg_contents[16]; /* maximum reg. width */ - - int rsn = gdb_remote_register_info(p, task, arg1, - &rs_pos, &rs_count, - &bytes); - pr_debug ("gdb register %lu => rsn %d p%u c%u b%u\n", - arg1, rsn, rs_pos, rs_count, bytes); - - if (rsn < 0) - break; - - /* If we want to extract register data, make sure - we're fetching at least that much. */ - BUG_ON(rs_count > 0 && rs_count < bytes); - /* Assert reg_contents size is right. */ - BUG_ON(sizeof(reg_contents) < bytes || - sizeof(reg_contents) < rs_count); - - /* Remaining packet too short? */ - if ((op_start + 2*bytes + 3) < p->input_buf_size) - break; - - /* 0-fill the register copy. XXX initialize - * it from rs->get() instead? - */ - memset (reg_contents, 0, sizeof(reg_contents)); - - /* Hex-unconvert all the bytes. */ - /* XXX: endianness adjust for count != bytes */ - for(j=0; jinput_buf[op_start+2*j], - p->input_buf[op_start+2*j+1]); - op_start += 2*bytes; - - if (rs_count) { /* real register */ - BUG_ON(rs_count > sizeof(reg_contents)); - rsv = task_user_regset_view(task); - BUG_ON(rsn >= rsv->n); - rs = & rsv->regsets[rsn]; - - /* Set the register value from reg_contents[]. */ - rc = (rs->set) (task, rs, rs_pos, rs_count, - reg_contents, NULL); - WARN_ON (rc); - } else { /* dummy register */ - ; - } - if (p->input_buf[op_start] == '#' && rc == 0) - push_output_packet (p, "OK"); - else - push_output_packet (p, "E01"); - } - break; - case 'm': /* ADDR,LENGTH */ - rc = sscanf(& p->input_buf[2], "%lx,%lx", &arg1, &arg2); - if (rc != 2) - push_output_packet(p, "E01"); - else { - size_t o = push_output_packet_start (p); - while (arg2 > 0) { - unsigned char value; - - /* Simply stop looping if requested - length was too large. gdb will - probably retry from this point - on. */ - if (p->output_buf_size + 5 > GDB_BUFMAX) - break; - - rc = access_process_vm(task, arg1, &value, 1, 0); - if (rc != 1) - break; /* EFAULT */ - else - push_output_hex (p, value); - - arg1++; - arg2--; - } - push_output_packet_end (p, o); - } - break; - case 'M': /* ADDR,LENGTH:XX */ - /* `i' will index p->input_buf to consume XX hex bytes. */ - rc = sscanf(& p->input_buf[2], "%lx,%lx:%n", - &arg1, &arg2, &i); - op_start = i + 2; /* Skip the leading $M also. */ - if (rc < 2) { - push_output_packet(p, "E01"); - break; - } - while (arg2 > 0) { - unsigned char value; - - /* Check that enough input bytes left for - * these two hex chars, plus the #XX checksum. - */ - if (i+4 >= p->input_buf_size) - break; - - value = byteme(p->input_buf[i], - p->input_buf[i+1]); - rc = access_process_vm(task, arg1, &value, 1, 1); - if (rc != 1) - break; /* EFAULT */ - - i += 2; - arg1++; - arg2--; - } - if (arg2 != 0) - push_output_packet(p, "E02"); - else - push_output_packet(p, "OK"); - break; + unsigned long arg1, arg2, arg3; + size_t op_start; + int rc = 0; + int i, j; + + pr_debug("gdb packet code %c\n", p->input_buf[1]); + + switch (p->input_buf[1]) { + case '?': + if (p->at_quiesce_do != UTRACE_STOP) { + /* shouldn't happen */ + p->stop_signals++; + rc = utrace_control(task, p->engine, UTRACE_INTERRUPT); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); + /* + * Note that we don't enqueue a reply packet here, + * but make gdb wait for a response from the + * utrace report_FOO callbacks. + */ + } else { + push_output_packet(p, p->stopcode); + } + break; + + case 'i': /* [ADDR[,NNN]] */ + case 's': /* [ADDR] */ + /* XXX: if !arch_has_single_step() ... then what? */ + case 'c': /* [ADDR] */ + rc = sscanf(&p->input_buf[2], "%lx,%lx", &arg1, &arg2); + /* XXX: args ignored */ + p->stopcode[0] = '\0'; + p->at_quiesce_do = + ((p->input_buf[1] == 'c' || !arch_has_single_step()) + ? UTRACE_RESUME : UTRACE_SINGLESTEP); + if (p->at_quiesce_do == UTRACE_SINGLESTEP) + p->stop_signals++; + rc = utrace_control(task, p->engine, p->at_quiesce_do); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); + break; + case 'C': /* SIG[;ADDR] */ + case 'S': /* SIG[;ADDR] */ + /* XXX: if !arch_has_single_step() ... then what? */ + case 'I': /* SIG[;ADDR[,NNN?]] */ + rc = sscanf(&p->input_buf[2], "%lx;%lx,%lx", &arg1, &arg2, + &arg3); + if (rc >= 1) /* SIG present */ + send_sig(map_signal_gdb2kern(arg1), task, 1); + + p->pass_signals++; + p->stopcode[0] = '\0'; + p->at_quiesce_do = + ((p->input_buf[1] == 'C' || !arch_has_single_step()) + ? UTRACE_RESUME : UTRACE_SINGLESTEP); + if (p->at_quiesce_do == UTRACE_SINGLESTEP) + p->stop_signals++; + + rc = utrace_control(task, p->engine, p->at_quiesce_do); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); + + /* Response will come at next report_signal. */ + break; + case 'D': + push_output_packet(p, "OK"); + /* NB: proc_gdb_release() performs actual utrace detach. */ + break; + case 'g': + op_start = push_output_packet_start(p); + + /* + * GDB_BUFMAX stands for some random large number, + * known to be larger than the number of gdb indexed + * registers. + */ + for (i = 0; i < GDB_BUFMAX; i++) { + unsigned rs_count; + unsigned rs_pos; + unsigned bytes; + const struct user_regset_view *rsv; + const struct user_regset *rs; + unsigned char reg_contents[MAX_REG_WIDTH]; + + int rsn = gdb_remote_register_info(p, task, i, + &rs_pos, &rs_count, + &bytes); + + if (rsn < 0) + break; + + /* + * If we want to extract register data, make sure + * we're fetching at least that much. + */ + BUG_ON(rs_count > 0 && rs_count < bytes); + /* Assert reg_contents size is right. */ + BUG_ON(sizeof(reg_contents) < bytes || + sizeof(reg_contents) < rs_count); + + if (rs_count) { /* real register */ + rsv = task_user_regset_view(task); + BUG_ON(rsn >= rsv->n); + rs = &rsv->regsets[rsn]; + + /* + * Extract the register values into + * reg_contents[]. + */ + rc = (rs->get)(task, rs, rs_pos, rs_count, + reg_contents, NULL); + if (rc) + break; + + } else { /* dummy value */ + memset(reg_contents, 0, sizeof(reg_contents)); + } + + /* + * Hex-dump it. + * XXX: endianness adjust for count != bytes + */ + /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u (", + i, rsn, rs_pos, rs_count, bytes); */ + for (j = 0; j < bytes; j++) { + /* pr_debug("%02x", reg_contents[j]); */ + push_output_hex(p, reg_contents[j]); + } + /* pr_debug(")\n"); */ + + } + push_output_packet_end(p, op_start); + break; + case 'G': + i = 0; + op_start = 2; /* use as input pointer, past $G in command */ + while (p->input_buf[op_start] != '#' && + op_start < p->input_buf_size) { + unsigned rs_count; + unsigned rs_pos; + unsigned bytes; + const struct user_regset_view *rsv; + const struct user_regset *rs; + unsigned char reg_contents[MAX_REG_WIDTH]; + + int rsn = gdb_remote_register_info(p, task, i, + &rs_pos, &rs_count, + &bytes); + /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u\n", + i, rsn, rs_pos, rs_count, bytes); */ + + if (rsn < 0) + break; + + /* + * If we want to extract register data, make sure + * we're fetching at least that much. + */ + BUG_ON(rs_count > 0 && rs_count < bytes); + /* Assert reg_contents size is right. */ + BUG_ON(sizeof(reg_contents) < bytes || + sizeof(reg_contents) < rs_count); + + /* Remaining packet too short? */ + if ((op_start + 2 * bytes + 3) < p->input_buf_size) + break; + + /* + * 0-fill the register copy. XXX initialize + * it from rs->get() instead? + */ + memset(reg_contents, 0, sizeof(reg_contents)); + + /* + * Hex-unconvert all the bytes. + * XXX: endianness adjust for count != bytes + */ + for (j = 0; j < bytes; j++) + reg_contents[j] = + byteme(p->input_buf[op_start + 2 * j], + p->input_buf[op_start + 2 * j + 1]); + op_start += 2 * bytes; + + if (rs_count) { /* real register */ + BUG_ON(rs_count > sizeof(reg_contents)); + rsv = task_user_regset_view(task); + BUG_ON(rsn >= rsv->n); + rs = &rsv->regsets[rsn]; + + /* Set register values from reg_contents[]. */ + rc = (rs->set) (task, rs, rs_pos, rs_count, + reg_contents, NULL); + if (rc) + break; + } else { /* dummy register */ + ; + } + } + if (p->input_buf[op_start] == '#' && rc == 0) + push_output_packet(p, "OK"); + else + push_output_packet(p, "E01"); + + break; + case 'p': /* REG */ + push_output_packet(p, "E01"); + break; + case 'P': /* REG=VAL */ + /* `i' will index p->input_buf to consume VAL hex bytes. */ + rc = sscanf(&p->input_buf[2], "%lx=%n", &arg1, &i); + op_start = i + 2; /* Skip the leading $P also */ + if (rc != 1) { + push_output_packet(p, "E01"); + } else { + unsigned rs_count; + unsigned rs_pos; + unsigned bytes; + const struct user_regset_view *rsv; + const struct user_regset *rs; + unsigned char reg_contents[MAX_REG_WIDTH]; + + int rsn = gdb_remote_register_info(p, task, arg1, + &rs_pos, &rs_count, + &bytes); + pr_debug("gdb register %lu => rsn %d p%u c%u b%u\n", + arg1, rsn, rs_pos, rs_count, bytes); + + if (rsn < 0) + break; + + /* + * If we want to extract register data, make sure + * we're fetching at least that much. + */ + BUG_ON(rs_count > 0 && rs_count < bytes); + /* Assert reg_contents size is right. */ + BUG_ON(sizeof(reg_contents) < bytes || + sizeof(reg_contents) < rs_count); + + /* Remaining packet too short? */ + if ((op_start + 2 * bytes + 3) < p->input_buf_size) + break; + + /* + * 0-fill the register copy. + * XXX initialize it from rs->get() instead? + */ + memset(reg_contents, 0, sizeof(reg_contents)); + + /* + * Hex-unconvert all the bytes. + * XXX: endianness adjust for count != bytes + */ + for (j = 0; j < bytes; j++) + reg_contents[j] = + byteme(p->input_buf[op_start + 2 * j], + p->input_buf[op_start + 2 * j + 1]); + op_start += 2 * bytes; + + if (rs_count) { /* real register */ + BUG_ON(rs_count > sizeof(reg_contents)); + rsv = task_user_regset_view(task); + BUG_ON(rsn >= rsv->n); + rs = &rsv->regsets[rsn]; + + /* Set register values from reg_contents[]. */ + rc = (rs->set) (task, rs, rs_pos, rs_count, + reg_contents, NULL); + WARN_ON(rc); + } + if (p->input_buf[op_start] == '#' && rc == 0) + push_output_packet(p, "OK"); + else + push_output_packet(p, "E01"); + } + break; + case 'm': /* ADDR,LENGTH */ + rc = sscanf(&p->input_buf[2], "%lx,%lx", &arg1, &arg2); + if (rc != 2) + push_output_packet(p, "E01"); + else { + size_t o = push_output_packet_start(p); + while (arg2 > 0) { + unsigned char value; + + /* + * Simply stop looping if requested length + * was too large. gdb will probably retry + * from this point on. + */ + if (p->output_buf_size + 5 > GDB_BUFMAX) + break; + + rc = access_process_vm(task, arg1, &value, 1, + 0); + if (rc != 1) + break; /* EFAULT */ + else + push_output_hex(p, value); + + arg1++; + arg2--; + } + push_output_packet_end(p, o); + } + break; + case 'M': /* ADDR,LENGTH:XX */ + /* `i' will index p->input_buf to consume XX hex bytes. */ + rc = sscanf(&p->input_buf[2], "%lx,%lx:%n", &arg1, &arg2, &i); + op_start = i + 2; /* Skip the leading $M also. */ + if (rc < 2) { + push_output_packet(p, "E01"); + break; + } + while (arg2 > 0) { + unsigned char value; + + /* + * Check that enough input bytes left for + * these two hex chars, plus the #XX checksum. + */ + if (i + 4 >= p->input_buf_size) + break; + + value = byteme(p->input_buf[i], p->input_buf[i + 1]); + rc = access_process_vm(task, arg1, &value, 1, 1); + if (rc != 1) + break; /* EFAULT */ + + i += 2; + arg1++; + arg2--; + } + if (arg2 != 0) + push_output_packet(p, "E02"); + else + push_output_packet(p, "OK"); + + break; + #ifdef CONFIG_HAVE_UPROBES - case 'Z': /* TYPE,ADDR,LENGTH */ - rc = sscanf(& p->input_buf[2], "%lu,%lx,%lx", &arg1, &arg2, &arg3); - pr_debug ("'Z' %lu %lx %lx\n", arg1, arg2, arg3); - if (rc != 3 || (arg1 > 1) /*|| (arg3 != 1)*/) + case 'Z': /* TYPE,ADDR,LENGTH */ + rc = sscanf(&p->input_buf[2], "%lu,%lx,%lx", &arg1, &arg2, + &arg3); + pr_debug("'Z' %lu %lx %lx\n", arg1, arg2, arg3); + if (rc != 3 || arg1 > 1) push_output_packet(p, "E03"); else { - struct gdb_uprobe *gup = NULL; + struct gdb_uprobe *gup; gup = find_gdb_uprobe(arg2, p); if (gup) { @@ -1183,20 +1173,21 @@ static void handle_gdb_command_packet (struct gdb_connection *p, struct task_str push_output_packet(p, "E06"); } else { push_output_packet(p, "OK"); - if (!rc) { /* register_uprobe succeed */ + if (!rc) { /* register_uprobe succeed */ INIT_LIST_HEAD(&gup->link); list_add_tail(&gup->link, &p->uprobes); } } } - break; - case 'z': /* TYPE,ADDR,LENGTH */ - rc = sscanf(& p->input_buf[2], "%lu,%lx,%lx", &arg1, &arg2, &arg3); - pr_debug ("'z' %lu %lx %lx\n", arg1, arg2, arg3); - if (rc != 3 || (arg1 > 1) /* || (arg3 != 1) */) + break; + case 'z': /* TYPE,ADDR,LENGTH */ + rc = sscanf(&p->input_buf[2], "%lu,%lx,%lx", &arg1, &arg2, + &arg3); + pr_debug("'z' %lu %lx %lx\n", arg1, arg2, arg3); + if (rc != 3 || arg1 > 1) push_output_packet(p, "E03"); else { - struct gdb_uprobe *gup = NULL; + struct gdb_uprobe *gup; gup = find_gdb_uprobe(arg2, p); if (gup) { @@ -1210,13 +1201,13 @@ static void handle_gdb_command_packet (struct gdb_connection *p, struct task_str gup->disarmed_p = 1; push_output_packet(p, "OK"); } else - push_output_packet(p, "E04"); - } - break; + push_output_packet(p, "E04"); + } + break; #endif /* CONFIG_HAVE_UPROBES */ - default: - push_output_packet (p, ""); - } + default: + push_output_packet(p, ""); + } } /* ------------------------------------------------------------------------ */ @@ -1228,366 +1219,368 @@ static void handle_gdb_command_packet (struct gdb_connection *p, struct task_str static int proc_gdb_open(struct inode *inode, struct file *filp) { struct task_struct *task = get_proc_task(inode); - int ret = -EBUSY; - struct gdb_connection *p; - struct list_head *l; - - pr_debug ("opened /proc/%d/gdb\n", task->pid); - - /* Reject kernel threads. */ - if (task->flags & PF_KTHREAD) { - ret = -EINVAL; - goto out; - } - - /* Reject if connection is for other than tg-leader thread. */ - if (task_pid_nr(task) != task_tgid_nr(task)) { - ret = -EINVAL; - goto out; - } - - mutex_lock (& gdb_connections_mutex); - - /* Reject if a connection exists for the thread group - * leader. - */ - list_for_each(l, &gdb_connections) { - p = list_entry (l, struct gdb_connection, link); - if (p->target == task_tgid_nr(task)) { - ret = -EBUSY; - goto out_mutex; - } - } - /* (Don't unlock yet, to defeat a race of two concurrent opens.) */ - - p = kzalloc(sizeof (struct gdb_connection), GFP_KERNEL); - if (!p) { - ret = -ENOMEM; - goto out_mutex; - } - - /* Send initial ping to gdb. */ - push_output_packet (p, ""); - - mutex_init(& p->output_mutex); - init_waitqueue_head(& p->output_wait); - - mutex_init(& p->input_mutex); - init_waitqueue_head(& p->input_wait); + int ret = -EBUSY; + struct gdb_connection *p; + + pr_debug("opened /proc/%d/gdb\n", task->pid); + + /* Reject kernel threads. */ + if (task->flags & PF_KTHREAD) { + ret = -EINVAL; + goto out; + } + + /* Reject if connection is for other than tg-leader thread. */ + if (task_pid_nr(task) != task_tgid_nr(task)) { + ret = -EINVAL; + goto out; + } + + mutex_lock(&gdb_connections_mutex); + + /* Reject if a connection exists for the thread group + * leader. + */ + list_for_each_entry(p, &gdb_connections, link) { + if (p->target == task_tgid_nr(task)) { + ret = -EBUSY; + goto out_mutex; + } + } + /* (Don't unlock yet, to defeat a race of two concurrent opens.) */ + + p = kzalloc(sizeof(struct gdb_connection), GFP_KERNEL); + if (!p) { + ret = -ENOMEM; + goto out_mutex; + } + + /* Send initial ping to gdb. */ + push_output_packet(p, ""); + + mutex_init(&p->output_mutex); + init_waitqueue_head(&p->output_wait); + + mutex_init(&p->input_mutex); + init_waitqueue_head(&p->input_wait); #ifdef CONFIG_HAVE_UPROBES INIT_LIST_HEAD(&p->uprobes); #endif - /* NB: During attach, we don't want to bother the target. - Soon though a send_sig will interrupt it. */ - p->at_quiesce_do = UTRACE_RESUME; + /* + * NB: During attach, we don't want to bother the target. + * Soon though a send_sig will interrupt it. + */ + p->at_quiesce_do = UTRACE_RESUME; p->target = task->tgid; - p->engine = utrace_attach_task(task, + p->engine = utrace_attach_task(task, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, - &gdb_utrace_ops, - p); - if (IS_ERR(p->engine) || p->engine==NULL) { - ret = -EBUSY; - goto out_free; - } - - ret = utrace_set_events(task, p->engine, - UTRACE_EVENT_SIGNAL_ALL| - UTRACE_EVENT(QUIESCE)| - UTRACE_EVENT(DEATH)| - UTRACE_EVENT(EXIT)| - UTRACE_EVENT(EXEC)| - UTRACE_EVENT(CLONE)); - pr_debug ("utrace_set_events sent, ret=%d\n", ret); - if (!ret) - ; + &gdb_utrace_ops, p); + if (IS_ERR(p->engine) || p->engine == NULL) { + ret = -EBUSY; + goto out_free; + } + ret = utrace_set_events(task, p->engine, + UTRACE_EVENT_SIGNAL_ALL | + UTRACE_EVENT(QUIESCE) | + UTRACE_EVENT(DEATH) | + UTRACE_EVENT(EXIT) | + UTRACE_EVENT(EXEC) | UTRACE_EVENT(CLONE)); + pr_debug("utrace_set_events sent, ret=%d\n", ret); utrace_engine_put(p->engine); - filp->private_data = p; + filp->private_data = p; - INIT_LIST_HEAD(& p->link); - list_add_tail(&p->link, &gdb_connections); + INIT_LIST_HEAD(&p->link); + list_add_tail(&p->link, &gdb_connections); - p->stop_signals ++; - ret = utrace_control (task, p->engine, UTRACE_INTERRUPT); - if (ret == -EINPROGRESS) - ret = utrace_barrier(task, p->engine); + p->stop_signals++; + ret = utrace_control(task, p->engine, UTRACE_INTERRUPT); + if (ret == -EINPROGRESS) + ret = utrace_barrier(task, p->engine); - goto out_mutex; + goto out_mutex; out_free: - kfree(p); + kfree(p); out_mutex: - mutex_unlock (& gdb_connections_mutex); + mutex_unlock(&gdb_connections_mutex); out: return ret; } - static int proc_gdb_release(struct inode *inode, struct file *filp) { struct task_struct *task = get_proc_task(inode); - struct gdb_connection *p = filp->private_data; - int ret = 0; + struct gdb_connection *p = filp->private_data; + int ret = 0; - mutex_lock (& gdb_connections_mutex); + mutex_lock(&gdb_connections_mutex); if (task == NULL) { - /* The thread is already gone; report_death was already called. */ + /* Thread is already gone; report_death was already called. */ pr_debug("gdb %d releasing old\n", p->target); } else if (p->at_quiesce_do != UTRACE_DETACH) { pr_debug("gdb %d releasing current\n", p->target); - ret = utrace_set_events(task, p->engine, 0); - if (ret == -EINPROGRESS) - ret = utrace_barrier(task, p->engine); - /* No more callbacks will be received! */ - - ret = utrace_control(task, p->engine, UTRACE_DETACH); /* => RESUME */ - if (ret == -EINPROGRESS) - ret = utrace_barrier(task, p->engine); - } + ret = utrace_set_events(task, p->engine, 0); + if (ret == -EINPROGRESS) + ret = utrace_barrier(task, p->engine); + + /* + * No more callbacks will be received! + * Detach implies Resume + */ + ret = utrace_control(task, p->engine, UTRACE_DETACH); + if (ret == -EINPROGRESS) + ret = utrace_barrier(task, p->engine); + } list_del(&p->link); mutex_unlock(&gdb_connections_mutex); #ifdef CONFIG_HAVE_UPROBES - { - struct list_head *l, *l2; - list_for_each_safe(l, l2, &p->uprobes) { - struct gdb_uprobe *gup = - list_entry(l, struct gdb_uprobe, link); - if (task) /* Not dead yet. */ - unregister_uprobe(&gup->up); - list_del(&gup->link); - kfree(gup); - } - } + gdb_unregister_uprobes(p, task); #endif /* CONFIG_HAVE_UPROBES */ - kfree(p); - + kfree(p); return ret; } - - static int proc_gdb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { - /* XXX: GDB usually thinks that a file name for "target - * remote" implies a serial port with tty-ish ioctl's - * available. We pretend to accept them all. */ - return 0; + /* + * XXX: GDB usually thinks that a file name for "target + * remote" implies a serial port with tty-ish ioctl's + * available. We pretend to accept them all. + */ + return 0; } - - -static ssize_t proc_gdb_read(struct file *filp, char __user *buf, - size_t count, loff_t *ppos) +static ssize_t proc_gdb_read(struct file *filp, char __user * buf, + size_t count, loff_t *ppos) { - struct gdb_connection *p = filp->private_data; + struct gdb_connection *p = filp->private_data; struct task_struct *task; - int rc = 0; - size_t len; + int rc = 0; + size_t len; - task = find_task_by_vpid (p->target); - if (!task) - return -EINVAL; + task = find_task_by_vpid(p->target); + if (!task) + return -EINVAL; - if ((p->output_buf_size <= p->output_buf_read) && - filp->f_flags & O_NONBLOCK) - return -EAGAIN; + if ((p->output_buf_size <= p->output_buf_read) && + filp->f_flags & O_NONBLOCK) + return -EAGAIN; again: - rc = wait_event_interruptible (p->output_wait, - (p->output_buf_size > p->output_buf_read)); - if (rc) - goto out; - - mutex_lock(&p->output_mutex); - - if(p->output_buf_size <= p->output_buf_read) { - mutex_unlock(&p->output_mutex); - goto again; - } - len = min (count, (size_t)(p->output_buf_size - p->output_buf_read)); - if (copy_to_user (buf, & p->output_buf[p->output_buf_read], len)) { - rc = -EFAULT; - goto out_unlock; - } - - pr_debug ("sent %u bytes (%ld left) data (%.*s)\n", - (unsigned)len, - ((long)p->output_buf_size-(long)p->output_buf_read)-len, - (int)len, & p->output_buf[p->output_buf_read]); - - p->output_buf_read += len; - rc = len; - - /* If whole packet is consumed, reset for next one. */ - BUG_ON (p->output_buf_read > p->output_buf_size); - if (p->output_buf_read == p->output_buf_size) { - p->output_buf_read = 0; - p->output_buf_size = 0; - } + rc = wait_event_interruptible(p->output_wait, + (p->output_buf_size > + p->output_buf_read)); + if (rc) + goto out; + + mutex_lock(&p->output_mutex); + + if (p->output_buf_size <= p->output_buf_read) { + mutex_unlock(&p->output_mutex); + goto again; + } + len = min(count, (size_t) (p->output_buf_size - p->output_buf_read)); + if (copy_to_user(buf, &p->output_buf[p->output_buf_read], len)) { + rc = -EFAULT; + goto out_unlock; + } + + pr_debug("sent %u bytes (%ld left) data (%.*s)\n", + (unsigned)len, + ((long)p->output_buf_size - (long)p->output_buf_read) - len, + (int)len, &p->output_buf[p->output_buf_read]); + + p->output_buf_read += len; + rc = len; + + /* If whole packet is consumed, reset for next one. */ + BUG_ON(p->output_buf_read > p->output_buf_size); + if (p->output_buf_read == p->output_buf_size) { + p->output_buf_read = 0; + p->output_buf_size = 0; + } out_unlock: - mutex_unlock(&p->output_mutex); + mutex_unlock(&p->output_mutex); out: - return rc; + return rc; } - -static ssize_t proc_gdb_write(struct file *filp, const char __user *buf, - size_t count, loff_t *ppos) +static ssize_t proc_gdb_write(struct file *filp, const char __user * buf, + size_t count, loff_t *ppos) { - struct gdb_connection *p = filp->private_data; - size_t last_input_buf_size; + struct gdb_connection *p = filp->private_data; + size_t last_input_buf_size; struct task_struct *task; - size_t len; - int ret = 0; + size_t len; + int ret = 0; - task = find_task_by_vpid (p->target); - if (!task) - return -EINVAL; + task = find_task_by_vpid(p->target); + if (!task) + return -EINVAL; again: - ret = wait_event_interruptible (p->input_wait, - (p->input_buf_size < GDB_BUFMAX)); - if (ret) - goto out; - - mutex_lock(&p->input_mutex); - if (p->input_buf_size == GDB_BUFMAX) { - mutex_unlock(&p->input_mutex); - goto again; - } - mutex_lock(&p->output_mutex); - - /* We now know there is some room in the input buffer. Upon - entry, the input_buf will either be empty, or contain a - partial gdb request packet. */ - - /* Copy the data. */ - len = min (count, (size_t)(GDB_BUFMAX - p->input_buf_size)); - if (copy_from_user (& p->input_buf[p->input_buf_size], buf, len)) { - ret = -EFAULT; - goto out_unlock; - } - - /* pr_debug ("received data %.*s\n", (int)len, & p->input_buf[p->input_buf_size]); */ - - p->input_buf_size += len; - ret = len; - - /* Process any packets in the buffer to restore the incoming - invariant. (Normal GDB will not send more than one packet - before waiting for a response.) */ - - /* We iterate until we can no longer shrink the input buffer. Usually - we will not iterate more than once, since there may be one +/- - ack byte and/or one gdb packet. */ - last_input_buf_size = 0; - while (p->input_buf_size - && p->input_buf_size != last_input_buf_size) { - last_input_buf_size = p->input_buf_size; - - if (p->input_buf[0] == '+') { - /* This must have been an ack to our - * previously output packet. - * Consume the input. - */ - memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); - } else if (p->input_buf[0] == '-') { - /* Whoops, a nak. Unfortunately, we don't - * handle transmission errors by - * retransmitting the last output_buf; it's - * already gone. OTOH we should not encounter - * transmission errors on a reliable channel - * such as a read syscall. - * Consume the input. - */ - printk(KERN_WARNING "Unexpected NAK received" - "on /proc/%d/gdb connection.\n", task_pid_nr(task)); - memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); - } else if (p->input_buf[0] == 3) { /* ^C == INTR */ - int rc; /* NB: don't overwrite 'ret'. */ - pr_debug ("received gdb interrupt\n"); - p->stop_signals ++; - rc = utrace_control(task, p->engine, UTRACE_INTERRUPT); - if (rc == -EINPROGRESS) - rc = utrace_barrier(task, p->engine); - /* p->at_quiesce_do will be set in report_signal(SIGNAL_REPORT) */ - /* NB: this packet does not generate an +/- ack. - Consume the input. */ - memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); - } else if (p->input_buf[0] == '$') { /* command packet */ - int j; - unsigned char checksum = 0; - for (j=1; jinput_buf_size-2; j++) { - if (p->input_buf[j] == '#') { - unsigned char checksum2; - checksum2 = byteme (p->input_buf[j+1], - p->input_buf[j+2]); - pr_debug ("received gdb packet %.*s\n", - j+3, & p->input_buf[0]); - if (checksum == checksum2) { - push_output (p, '+'); - handle_gdb_command_packet (p, task); - } else { - push_output (p, '-'); - } - /* Consume the whole packet. */ - p->input_buf_size -= (j+3); - memmove(&p->input_buf[0], &p->input_buf[j+3], - p->input_buf_size); - break; - } else { - checksum += p->input_buf[j]; - } - } /* End searching for end of packet */ - - /* We may not have found the # - * checksum. If so, leave the partial packet - * in input_buf. Since input_buf_size will - * not have decreased, the while() loop above - * will detect a fixpoint and exit. - * - * Alternately, there could be another gdb packet - * just behind the one we just consumed. In this - * we'll iterate one more time in this loop. - */ - } else { /* junk character */ - printk(KERN_WARNING "Unexpected character (%x) received" - " on /proc/%d/gdb connection.\n", - (int) p->input_buf[0], task_pid_nr(task)); - /* Consume the input. */ - memmove (&p->input_buf[0], &p->input_buf[1], --p->input_buf_size); - } - } - + ret = wait_event_interruptible(p->input_wait, + (p->input_buf_size < GDB_BUFMAX)); + if (ret) + goto out; + + mutex_lock(&p->input_mutex); + if (p->input_buf_size == GDB_BUFMAX) { + mutex_unlock(&p->input_mutex); + goto again; + } + mutex_lock(&p->output_mutex); + + /* We now know there is some room in the input buffer. Upon + entry, the input_buf will either be empty, or contain a + partial gdb request packet. */ + + /* Copy the data. */ + len = min(count, (size_t) (GDB_BUFMAX - p->input_buf_size)); + if (copy_from_user(&p->input_buf[p->input_buf_size], buf, len)) { + ret = -EFAULT; + goto out_unlock; + } + + /* + * pr_debug("received data %.*s\n", (int)len, + * &p->input_buf[p->input_buf_size]); + */ + + p->input_buf_size += len; + ret = len; + + /* + * Process any packets in the buffer to restore the incoming + * invariant. (Normal GDB will not send more than one packet before + * waiting for a response.) + */ + + /* + * We iterate until we can no longer shrink the input buffer. + * Usually we will not iterate more than once, since there may be + * one +/- ack byte and/or one gdb packet. + */ + last_input_buf_size = 0; + while (p->input_buf_size && p->input_buf_size != last_input_buf_size) { + last_input_buf_size = p->input_buf_size; + + if (p->input_buf[0] == '+') { + /* + * This must have been an ack to our + * previously output packet. + * Consume the input. + */ + memmove(&p->input_buf[0], &p->input_buf[1], + --p->input_buf_size); + } else if (p->input_buf[0] == '-') { + /* + * Whoops, a nak. Unfortunately, we don't + * handle transmission errors by + * retransmitting the last output_buf; it's + * already gone. OTOH we should not encounter + * transmission errors on a reliable channel + * such as a read syscall. + * Consume the input. + */ + printk(KERN_WARNING "Unexpected NAK received" + "on /proc/%d/gdb connection.\n", + task_pid_nr(task)); + memmove(&p->input_buf[0], &p->input_buf[1], + --p->input_buf_size); + } else if (p->input_buf[0] == 3) { /* ^C == INTR */ + int rc; /* NB: don't overwrite 'ret'. */ + pr_debug("received gdb interrupt\n"); + p->stop_signals++; + rc = utrace_control(task, p->engine, UTRACE_INTERRUPT); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); + + /* + * p->at_quiesce_do will be set in + * report_signal(SIGNAL_REPORT). NB: this packet + * does not generate an +/- ack. Consume the input. + */ + memmove(&p->input_buf[0], &p->input_buf[1], + --p->input_buf_size); + } else if (p->input_buf[0] == '$') { /* command packet */ + int j; + unsigned char checksum = 0; + for (j = 1; j < p->input_buf_size - 2; j++) { + if (p->input_buf[j] == '#') { + unsigned char checksum2; + checksum2 = byteme(p->input_buf[j + 1], + p->input_buf[j + 2]); + pr_debug("received gdb packet %.*s\n", + j + 3, &p->input_buf[0]); + if (checksum == checksum2) { + push_output(p, '+'); + handle_gdb_command_packet(p, + task); + } else { + push_output(p, '-'); + } + /* Consume the whole packet. */ + p->input_buf_size -= (j + 3); + memmove(&p->input_buf[0], + &p->input_buf[j + 3], + p->input_buf_size); + break; + } else { + checksum += p->input_buf[j]; + } + } /* End searching for end of packet */ + + /* + * We may not have found the # + * checksum. If so, leave the partial packet + * in input_buf. Since input_buf_size will + * not have decreased, the while() loop above + * will detect a fixpoint and exit. + * + * Alternately, there could be another gdb packet + * just behind the one we just consumed. In this + * we'll iterate one more time in this loop. + */ + } else { /* junk character */ + printk(KERN_WARNING "Unexpected character (%x) received" + " on /proc/%d/gdb connection.\n", + (int)p->input_buf[0], task_pid_nr(task)); + /* Consume the input. */ + memmove(&p->input_buf[0], &p->input_buf[1], + --p->input_buf_size); + } + } + out_unlock: - wake_up(&p->input_wait); /* Probably have more room in input_buf. */ - wake_up(&p->output_wait); /* Probably have data in output_buf. */ + /* Probably have more room in input_buf. */ + wake_up(&p->input_wait); + /* Probably have data in output_buf. */ + wake_up(&p->output_wait); - mutex_unlock(&p->output_mutex); - mutex_unlock(&p->input_mutex); + mutex_unlock(&p->output_mutex); + mutex_unlock(&p->input_mutex); out: - return ret; + return ret; } - const struct file_operations proc_gdb_operations = { - .open = proc_gdb_open, - .read = proc_gdb_read, - .write = proc_gdb_write, - .release = proc_gdb_release, - .ioctl = proc_gdb_ioctl, + .open = proc_gdb_open, + .read = proc_gdb_read, + .write = proc_gdb_write, + .release = proc_gdb_release, + .ioctl = proc_gdb_ioctl, }; - - From envoi at campaigns.media-sender.net Wed Sep 23 11:56:59 2009 From: envoi at campaigns.media-sender.net (IC Telecom) Date: Wed, 23 Sep 2009 13:56:59 +0200 (CEST) Subject: =?iso-8859-15?q?Illimite_=3A_Communications_-_Internet_-_t=E9l?= =?iso-8859-15?q?=E9phones?= Message-ID: <1011303148415.1103436668.1253707019817@enginex1.emv2.com> An HTML attachment was scrubbed... URL: From hot-deals at clubvacationdeals.com Wed Sep 23 18:14:56 2009 From: hot-deals at clubvacationdeals.com (Club Vacation Deals) Date: Wed, 23 Sep 2009 14:14:56 -0400 Subject: Live a different Christmas on the beach Message-ID: An HTML attachment was scrubbed... URL: From jan.kratochvil at redhat.com Wed Sep 23 20:40:44 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Wed, 23 Sep 2009 22:40:44 +0200 Subject: Q: what user_enable_single_step() actually means? In-Reply-To: <20090923003654.EA6EB13F37@magilla.sf.frob.com> References: <20090921025335.GA13423@redhat.com> <20090921051352.319BAB1@magilla.sf.frob.com> <20090921190836.GA27320@redhat.com> <20090923003654.EA6EB13F37@magilla.sf.frob.com> Message-ID: <20090923204044.GA11131@host0.dyn.jankratochvil.net> On Wed, 23 Sep 2009 02:36:54 +0200, Roland McGrath wrote: > It would be worthwhile to cons a version of this test case that uses > PTRACE_SINGLESTEP instead of PTRACE_SYSCALL. I think your situation > is tickling the same issue, but we should have an empirical test. [...] > I have a fix in hand that I'll send upstream before too long. But perhaps > it should wait for the PTRACE_SINGLESTEP version of the test case. Seeing you already added one yourself. 2009-09-23 05:31 roland * tests/: Makefile.am (1.56), step-from-clone.c (1.1): Add step-from-clone test. Regards, Jan From oleg at redhat.com Wed Sep 23 20:51:14 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 23 Sep 2009 22:51:14 +0200 Subject: utrace_control(XXXSTEP)->is_setting_trap_flag() is not safe Message-ID: <20090923205114.GA12303@redhat.com> Btw, I believe we have another problem. utrace_control(SINGLESTEP) calls user_enable_single_step() under utrace->lock. I don't really understand the magic in enable_single_step() but is_setting_trap_flag() calls access_process_vm(), this doesn't look good under spinlock. Hmm. Not sure how to fix this... Oleg. From roland at redhat.com Wed Sep 23 21:01:27 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 23 Sep 2009 14:01:27 -0700 (PDT) Subject: Q: what user_enable_single_step() actually means? In-Reply-To: Jan Kratochvil's message of Wednesday, 23 September 2009 22:40:44 +0200 <20090923204044.GA11131@host0.dyn.jankratochvil.net> References: <20090921025335.GA13423@redhat.com> <20090921051352.319BAB1@magilla.sf.frob.com> <20090921190836.GA27320@redhat.com> <20090923003654.EA6EB13F37@magilla.sf.frob.com> <20090923204044.GA11131@host0.dyn.jankratochvil.net> Message-ID: <20090923210127.A3D6D22@magilla.sf.frob.com> > On Wed, 23 Sep 2009 02:36:54 +0200, Roland McGrath wrote: > > It would be worthwhile to cons a version of this test case that uses > > PTRACE_SINGLESTEP instead of PTRACE_SYSCALL. I think your situation > > is tickling the same issue, but we should have an empirical test. > [...] > > I have a fix in hand that I'll send upstream before too long. But perhaps > > it should wait for the PTRACE_SINGLESTEP version of the test case. > > Seeing you already added one yourself. Yes, it was easy enough to make the variant and I wanted to test it. I did so, and submitted the fix upstream, and Linus merged it. I didn't ask for it to be put in stable branches, since we probably don't care. Thanks, Roland From roland at redhat.com Wed Sep 23 21:13:21 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 23 Sep 2009 14:13:21 -0700 (PDT) Subject: utrace_control(XXXSTEP)->is_setting_trap_flag() is not safe In-Reply-To: Oleg Nesterov's message of Wednesday, 23 September 2009 22:51:14 +0200 <20090923205114.GA12303@redhat.com> References: <20090923205114.GA12303@redhat.com> Message-ID: <20090923211321.0F09A22@magilla.sf.frob.com> > Btw, I believe we have another problem. utrace_control(SINGLESTEP) calls > user_enable_single_step() under utrace->lock. I don't really understand > the magic in enable_single_step() but is_setting_trap_flag() calls > access_process_vm(), this doesn't look good under spinlock. Yes, this has been on my list of concerns for a long time but I always forget about it. Perhaps I intentionally let it lie as a test for reviewers' attention to detail, we'll never know. :-) > Hmm. Not sure how to fix this... Well, one thing it can do is just punt them down to UTRACE_REPORT. It's only a non-guaranteed optimization that these effects happen directly from utrace_control() without being reinforced by a final report_quiesce/report_signal callback, after all. Most or all other machines do not have anything complex or blocky going on inside those calls at all. So potentially we could have arch macros and punt only on x86. But anyway. I'd sort of intended to leave this undecided until we get more final certainty on the locking corners of the utrace API. For this and other purposes it would be advantageous to use a mutex rather than a spin lock for the utrace lock. But that doesn't mesh with the hairy RCU guarantees we try to make to avoid callers needing task refs. So perhaps we'll in the end sort all that out differently and have a mutex. Then it would be plausible to hold that mutex while doing access_process_vm, though it's still not ideal to have "instant" async utrace ops like set_events and detach block on something external like arbitrary user page faults. So perhaps independent of the mutex/spin question (which we don't need to get into right this minute), we can devise some scheme to avoid wanting to hold that lock while doing user_enable_single_step. I haven't lately thought through what exactly is getting synchronized there that matters. Thanks, Roland From oleg at redhat.com Wed Sep 23 22:18:07 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 00:18:07 +0200 Subject: [PATCH 53-55] (Was: Q: what user_enable_single_step() actually means?) Message-ID: <20090923221807.GA16512@redhat.com> On 09/22, Roland McGrath wrote: > > I think the only cases where you can have a ptrace stop followed by > actually taking the ret_from_sys_call path are tracehook_report_clone stops > (i.e. the stop inside a clone/fork/vfork syscall). If you last used > PTRACE_CONT or whatever and then hit PTRACE_EVENT_FORK et al, resuming with > PTRACE_SYSCALL will fail to hit the syscall-exit report for that fork/clone > syscall. Yes, but this has nothing to do with utrace-ptrace. If we last used PTRACE_CONT, the tracee stops in utrace_resume() path before return to the user-mode, syscall_trace_leave() can't be called. > I added ptrace-tests/tests/syscall-from-clone.c for this case. Cool! Both tests fail. The 1st one is clear, ptrace_report_clone() is not finished yet. But the 2nd test-case reveals the problem: PTRACE_SINGLESTEP works exactly as I expected, but I didn't know that PTRACE_SINGLESTEP shouldn't bypass the syscall-exit stop! Oleg. From oleg at redhat.com Wed Sep 23 22:18:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 00:18:10 +0200 Subject: [PATCH 53] PTRACE_SYSCALL after PTRACE_EVENT_VFORK should trigger SYSCALL_EXIT Message-ID: <20090923221810.GA16516@redhat.com> The new ptrace-tests/tests/syscall-from-clone.c fails as expected. Because, following your suggestion, I postponed the "final" changes in ptrace_report_clone() until we fix the more important things. But since we have the new test-case, add the trivial fix. ptrace_report_clone() still needs changes! Will do later. --- kernel/ptrace.c | 4 ++++ 1 file changed, 4 insertions(+) --- PU/kernel/ptrace.c~53_CLONE_ATTACH_SYSCALL 2009-09-23 20:49:33.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-23 20:51:47.000000000 +0200 @@ -99,6 +99,8 @@ void __ptrace_link(struct task_struct *c static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */ static int ptrace_attach_task(struct task_struct *tracee, int options); static void ptrace_abort_attach(struct task_struct *tracee); +static void ptrace_resume_ck_syscall(struct utrace_engine *engine, + struct task_struct *tracee, long data); static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee) { @@ -223,6 +225,7 @@ static u32 ptrace_report_clone(enum utra ev->ev_message = child->pid; ev->ev_code = (event << 8) | SIGTRAP; + ev->ev_resume = ptrace_resume_ck_syscall; ret = UTRACE_STOP; } @@ -234,6 +237,7 @@ static u32 ptrace_report_clone(enum utra ev->ev_message = child->pid; ev->ev_options = PTRACE_O_TRACEVFORKDONE; ev->ev_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP; + ev->ev_resume = ptrace_resume_ck_syscall; ret = UTRACE_STOP; } From oleg at redhat.com Wed Sep 23 22:18:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 00:18:12 +0200 Subject: [PATCH 54] PTRACE_SINGLESTEP shouldn't bypass SYSCALL_EXIT Message-ID: <20090923221812.GA16523@redhat.com> The new test ptrace-tests/tests/step-from-clone.c fails. I didn't know that PTRACE_SINGLESTEP is not "user-mode only". I thought that the next stop should happen only after return to user-mode. However, the current behaviour is that PTRACE_SINGLESTEP acts like PTRACE_SYSCALL (but see below), if the tracee is not going to return to user-mode yet. Say, PTRACE_EVENT_VFORK. step-from-clone still fails because PTRACE_O_TRACESYSGOOD adds 0x80 to ->ex_code even after PTRACE_SINGLESTEP, see the next patch. --- kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- PU/kernel/ptrace.c~54_STEP_IMPLIES_O_SYSCALL 2009-09-23 20:51:47.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-23 21:52:46.000000000 +0200 @@ -947,7 +947,7 @@ static void do_ptrace_resume(struct utra { struct ptrace_context *context = ptrace_context(engine); - if (request == PTRACE_SYSCALL) + if (request == PTRACE_SYSCALL || action != UTRACE_RESUME) context->options |= PTRACE_O_TRACE_SYSCALL; else context->options &= ~PTRACE_O_TRACE_SYSCALL; From oleg at redhat.com Wed Sep 23 22:18:15 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 00:18:15 +0200 Subject: [PATCH 55] workaround to pass the assert() at step-from-clone.c:193 Message-ID: <20090923221815.GA16526@redhat.com> This is the temporary fix for the new step-from-clone.c test-case. Actually kludge, not the fix. But I don't understand the rationale behind the current behaviour yet. So, this test does: ptrace(PTRACE_SETOPTIONS, PTRACE_O_TRACESYSGOOD); ptrace(PTRACE_CONT); // tracee reports PTRACE_EVENT_FORK ptrace(PTRACE_SINGLESTEP) Now the tracer expects to get the notification from syscall-exit stop for "fork ()", but at the same time it expects assert ((status >> 8) == SIGTRAP); This looks a bit strange to me, usually PTRACE_O_TRACESYSGOOD adds 0x80. Yes, I understand why this happens with the vanilla kernel, without PTRACE_SYSCALL TIF_SYSCALL_FTRACE is not set when syscall_trace_leave() is called, we got this report due to send_sigtrap(). And send_sigtrap() means we really report the signal, I mean utrace-ptrace should do send_sigtrap() too, not just report SIGTRAP. We need the valid context->siginfo which indicates the tracer can change/clear ->si_signo on resume. And of course, we can't rely on syscall_trace_leave() in this case, we stop before return to the user-mode after syscall_trace_leave() was already called. Oh. I'll fix this later. --- kernel/ptrace.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) --- PU/kernel/ptrace.c~55_STEP_IGNORES_TRACESYSGOOD 2009-09-23 21:52:46.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-23 22:26:59.000000000 +0200 @@ -267,8 +267,9 @@ static void push_syscall_event(struct pt ev->ev_options = PTRACE_O_TRACE_SYSCALL; ev->ev_resume = ptrace_resume_syscall; - ev->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? - (SIGTRAP | 0x80) : SIGTRAP; + ev->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) && + (context->resume == UTRACE_RESUME) ? + (SIGTRAP | 0x80) : SIGTRAP; } static u32 ptrace_report_syscall_entry(u32 action, @@ -952,6 +953,8 @@ static void do_ptrace_resume(struct utra else context->options &= ~PTRACE_O_TRACE_SYSCALL; + context->resume = action; + if (!ev_empty(context)) { struct ptrace_event *ev = ev_pop(context); @@ -969,7 +972,6 @@ static void do_ptrace_resume(struct utra } } - context->resume = action; ptrace_wake_up(engine, tracee, action); } From roland at redhat.com Wed Sep 23 22:39:18 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 23 Sep 2009 15:39:18 -0700 (PDT) Subject: [PATCH 53-55] (Was: Q: what user_enable_single_step() actually means?) In-Reply-To: Oleg Nesterov's message of Thursday, 24 September 2009 00:18:07 +0200 <20090923221807.GA16512@redhat.com> References: <20090923221807.GA16512@redhat.com> Message-ID: <20090923223918.1B10EE06@magilla.sf.frob.com> > Yes, but this has nothing to do with utrace-ptrace. If we last used > PTRACE_CONT, the tracee stops in utrace_resume() path before return to > the user-mode, syscall_trace_leave() can't be called. If I follow what you mean, that is just the x86 bug (now fixed upstream). > Both tests fail. The 1st one is clear, ptrace_report_clone() is not > finished yet. But the 2nd test-case reveals the problem: > PTRACE_SINGLESTEP works exactly as I expected, but I didn't know that > PTRACE_SINGLESTEP shouldn't bypass the syscall-exit stop! No, it's weirder than that. PTRACE_SINGLESTEP means that you are not doing syscall tracing, since it's not PTRACE_SYSCALL. But the behavior (implemented by TIF_SINGLESTEP on x86) of single-step is to simulate a hardware trap after a system call completes, so that from the userland perspective single-step over a syscall insn is like just any other insn (albeit one with many strange side effects). So it's not syscall exit tracing that fires as far as the semantics, it's a "normal" single-step trap (i.e. pretends to be). It just so happens that on x86 the implementation of this shares the assembly code paths with syscall tracing, so the simulation happens in syscall_trace_leave: /* * If we are single-stepping, synthesize a trap to follow the * system call instruction. */ if (test_thread_flag(TIF_SINGLESTEP) && tracehook_consider_fatal_signal(current, SIGTRAP)) send_sigtrap(current, regs, 0, TRAP_BRKPT); It's a further oddity that you can single-step (or not) "into" the system call and then get a ptrace stop "inside" it, that being for PTRACE_EVENT_FORK et al. From there, the thread register state shows it being after the syscall insn, but (in vanilla ptrace, and at the time of report_clone callbacks at utrace level) without the return value register having been written yet. So if you were single-stepping, you want to PTRACE_SINGLESTEP from there and still have it stop right after the syscall rather than one insn later. The debugger would not show the user the thread state at report_clone time (i.e. PTRACE_EVENT_CLONE in vanilla ptrace) but just do its attaching and bookkeeping and then repeat PTRACE_SINGLESTEP to see the state after the completion of the one insn that happened to be the syscall insn. Thanks, Roland From roland at redhat.com Wed Sep 23 22:45:36 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 23 Sep 2009 15:45:36 -0700 (PDT) Subject: [PATCH 54] PTRACE_SINGLESTEP shouldn't bypass SYSCALL_EXIT In-Reply-To: Oleg Nesterov's message of Thursday, 24 September 2009 00:18:12 +0200 <20090923221812.GA16523@redhat.com> References: <20090923221812.GA16523@redhat.com> Message-ID: <20090923224536.EA282E06@magilla.sf.frob.com> > However, the current behaviour is that PTRACE_SINGLESTEP acts like > PTRACE_SYSCALL (but see below), if the tracee is not going to return > to user-mode yet. Say, PTRACE_EVENT_VFORK. Not really. Given what I just wrote, I'm not sure if you want me to merge these. I'm sure you'll be changing it entirely and these look to me to be enough in the wrong direction that they are not incrementally useful. My utrace tree is still forked from 2.6.31. If you want me to merge the current upstream tree so you get b60e714d folded in, I can do that. Thanks, Roland From oleg at redhat.com Wed Sep 23 23:07:48 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 01:07:48 +0200 Subject: [PATCH 53-55] (Was: Q: what user_enable_single_step() actually means?) In-Reply-To: <20090923223918.1B10EE06@magilla.sf.frob.com> References: <20090923221807.GA16512@redhat.com> <20090923223918.1B10EE06@magilla.sf.frob.com> Message-ID: <20090923230748.GA17618@redhat.com> On 09/23, Roland McGrath wrote: > > > Yes, but this has nothing to do with utrace-ptrace. If we last used > > PTRACE_CONT, the tracee stops in utrace_resume() path before return to > > the user-mode, syscall_trace_leave() can't be called. > > If I follow what you mean, that is just the x86 bug (now fixed upstream). Not sure we understand each other, but no. Yes I think the fix is nice, but afaics it can't help utrace-ptrace. The tracee stops and reports PTRACE_EVENT_FORK from do_notify_resume(), after that syscall_trace_leave() can't (and must not) be called. > > Both tests fail. The 1st one is clear, ptrace_report_clone() is not > > finished yet. But the 2nd test-case reveals the problem: > > PTRACE_SINGLESTEP works exactly as I expected, but I didn't know that > > PTRACE_SINGLESTEP shouldn't bypass the syscall-exit stop! > > No, it's weirder than that. Yes, yes, I see, > [...snip...] Thanks! I need to think about this all, will send more fixes tomorrow. Today I want to do some context->sighand changes. Oleg. From roland at redhat.com Wed Sep 23 23:19:55 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 23 Sep 2009 16:19:55 -0700 (PDT) Subject: [PATCH 53-55] (Was: Q: what user_enable_single_step() actually means?) In-Reply-To: Oleg Nesterov's message of Thursday, 24 September 2009 01:07:48 +0200 <20090923230748.GA17618@redhat.com> References: <20090923221807.GA16512@redhat.com> <20090923223918.1B10EE06@magilla.sf.frob.com> <20090923230748.GA17618@redhat.com> Message-ID: <20090923231955.BA3A3E06@magilla.sf.frob.com> > The tracee stops and reports PTRACE_EVENT_FORK from do_notify_resume(), > after that syscall_trace_leave() can't (and must not) be called. Oh, I see what you mean. That is all under your control from the utrace API level. You can use a syscall-exit report first if you want to for keeping track of things, but yes, the actual stop will not be until later. Thanks, Roland From oleg at redhat.com Wed Sep 23 23:24:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 01:24:21 +0200 Subject: [PATCH 54] PTRACE_SINGLESTEP shouldn't bypass SYSCALL_EXIT In-Reply-To: <20090923224536.EA282E06@magilla.sf.frob.com> References: <20090923221812.GA16523@redhat.com> <20090923224536.EA282E06@magilla.sf.frob.com> Message-ID: <20090923232421.GA19036@redhat.com> On 09/23, Roland McGrath wrote: > > > However, the current behaviour is that PTRACE_SINGLESTEP acts like > > PTRACE_SYSCALL (but see below), if the tracee is not going to return > > to user-mode yet. Say, PTRACE_EVENT_VFORK. > > Not really. Given what I just wrote, I'm not sure if you want me > to merge these. I'm sure you'll be changing it entirely and these > look to me to be enough in the wrong direction that they are not > incrementally useful. Yes. these changes are temporary hacks. I did them mostly to ensure I really understand the pending problems. > My utrace tree is still forked from 2.6.31. If you want me to merge the > current upstream tree so you get b60e714d folded in, I can do that. I don't care ;) Because currently I do not pull from your tree. And I already applied b60e714d to my tree. Oleg. From oleg at redhat.com Thu Sep 24 00:40:02 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 02:40:02 +0200 Subject: [PATCH 56-58] context->siginfo fixes Message-ID: <20090924004002.GA25852@redhat.com> I think ptrace_report_signal() is mostly finished. Unlike vanilla kernel, the tracer fixups the context of ->siginfo if we change si_signo, not the tracee. task_pid_vnr() is not namespace friendly, but I think we don't care. At least now. And the question: ptrace_report_signal: /* * If the (new) signal is now blocked, requeue it. */ if (sigismember(&task->blocked, info->si_signo)) { send_sig_info(info->si_signo, info, task); return resume | UTRACE_SIGNAL_IGN; } This was copy-and-pasted from the old code. Shouldn't we rely use UTRACE_SIGNAL_HOLD instead ? Oleg. From oleg at redhat.com Thu Sep 24 00:40:04 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 02:40:04 +0200 Subject: [PATCH 56] ptrace_resume_signal() should use context->siginfo under ->siglock Message-ID: <20090924004004.GA25860@redhat.com> - Change ptrace_resume_signal() to use context->siginfo under ->siglock, like ptrace_{get,set}siginfo() do. - Document why this is safe. - Also, use ACCESS_ONCE() which implies the compiler barrier. This is only theoretical issue, but still. --- kernel/ptrace.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) --- PU/kernel/ptrace.c~56_RESUME_SIGNAL_SIGLOCK 2009-09-23 22:26:59.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-24 02:03:09.000000000 +0200 @@ -326,24 +326,31 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_STOP; } -/* - * XXX: This all is wrong/racy/crashable - */ static void ptrace_resume_signal(struct utrace_engine *engine, struct task_struct *tracee, long data) { - siginfo_t *info = ptrace_context(engine)->siginfo; + unsigned long flags; + siginfo_t *info; - if (WARN_ON(!info)) + if (!lock_task_sighand(tracee, &flags)) return; + /* + * Make sure the compiler reads ->siginfo only once, if we race + * with SIGKILL ->siginfo can be cleared under us. But since we + * hold ->siglock the memory it points to can't go away, see the + * comment in ptrace_report_signal() below. + */ + info = ACCESS_ONCE(ptrace_context(engine)->siginfo); + WARN_ON(!info && !(tracee->signal->flags & SIGNAL_GROUP_EXIT)); - if (info->si_signo != data) { + if (likely(info) && info->si_signo != data) { info->si_signo = data; info->si_code = SI_USER; info->si_errno = 0; info->si_pid = task_pid_vnr(current); info->si_uid = current_uid(); } + unlock_task_sighand(tracee, &flags); } static u32 ptrace_report_signal(u32 action, @@ -404,8 +411,12 @@ static u32 ptrace_report_signal(u32 acti default: WARN_ON(context->siginfo); context->siginfo = info; - // Make sure the next UTRACE_SIGNAL_REPORT - // will clear context->siginfo + /* + * context->siginfo points to the caller's stack. + * Make sure we can never escape from get_signal_to_deliver() + * without taking ->siglock and subsequent UTRACE_SIGNAL_REPORT + * which clears context->siginfo. + */ utrace_control(task, engine, UTRACE_INTERRUPT); ev = ev_push(context); From oleg at redhat.com Thu Sep 24 00:40:07 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 02:40:07 +0200 Subject: [PATCH 57] UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL Message-ID: <20090924004007.GA25863@redhat.com> ptrace_report_signal(UTRACE_SIGNAL_HANDLER) should be never called with a valid context->siginfo, move the corresponding WARN_ON() up. --- kernel/ptrace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- PU/kernel/ptrace.c~57_SIGNAL_HANDLER_WARN_ALWAYS 2009-09-24 02:03:09.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-24 02:14:17.000000000 +0200 @@ -374,10 +374,10 @@ static u32 ptrace_report_signal(u32 acti switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: - if (resume != UTRACE_RESUME) { - if (WARN_ON(context->siginfo)) - context->siginfo = NULL; + if (WARN_ON(context->siginfo)) + context->siginfo = NULL; + if (resume != UTRACE_RESUME) { ev = ev_push(context); ev->ev_code = SIGTRAP; From oleg at redhat.com Thu Sep 24 00:40:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 02:40:09 +0200 Subject: [PATCH 58] introduce context_siginfo() helper Message-ID: <20090924004009.GA25871@redhat.com> Not sure you will like it, hence the separate patch. ptrace_{get,set}siginfo() need ACCESS_ONCE() to fix the theoretical problem, and they also need a comment to explain why it is safe to dereference ->siginfo under ->siglock. I think it would be more readable if we add the trivial helper, just to avoid duplicating the comment. --- kernel/ptrace.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) --- PU/kernel/ptrace.c~58_CONTEXT_SIGINFO 2009-09-24 02:14:17.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-24 02:26:26.000000000 +0200 @@ -326,6 +326,17 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_STOP; } +static inline siginfo_t *context_siginfo(struct ptrace_context *context) +{ + /* + * Make sure the compiler reads ->siginfo only once, if we race + * with SIGKILL ->siginfo can be cleared under us. But since we + * hold ->siglock the memory it points to can't go away, see the + * comment in ptrace_report_signal() below. + */ + return ACCESS_ONCE(context->siginfo); +} + static void ptrace_resume_signal(struct utrace_engine *engine, struct task_struct *tracee, long data) { @@ -334,13 +345,8 @@ static void ptrace_resume_signal(struct if (!lock_task_sighand(tracee, &flags)) return; - /* - * Make sure the compiler reads ->siginfo only once, if we race - * with SIGKILL ->siginfo can be cleared under us. But since we - * hold ->siglock the memory it points to can't go away, see the - * comment in ptrace_report_signal() below. - */ - info = ACCESS_ONCE(ptrace_context(engine)->siginfo); + + info = context_siginfo(ptrace_context(engine)); WARN_ON(!info && !(tracee->signal->flags & SIGNAL_GROUP_EXIT)); if (likely(info) && info->si_signo != data) { From joerg.nickl at copeberlin.de Thu Sep 24 00:58:35 2009 From: joerg.nickl at copeberlin.de (=?utf-8?B?SsO2cmcgTmlja2wg?=) Date: Thu, 24 Sep 2009 02:58:35 +0200 Subject: =?utf-8?q?Votar_com_intelig=C3=AAncia_e_raz=C3=A3o?= Message-ID: <20090924005835.7639.1686209538.swift@www.artist-newsletter.de> VOTAR COM INTELIG?NCIA E RAZ?O Em quem vai confiar o seu voto? Veja a resposta no final deste inqu?rito Em quem confiaria ? guarda o seu dinheiro? Jos? S?crates Manuela F. Leite Paulo Portas Francisco Lou?? Jer?nimo de Sousa Tem de sair de casa. A quem confiaria os seus filhos? Jos? S?crates Manuela F. Leite Paulo Portas Francisco Lou?? Jer?nimo de Sousa Precisa de ajuda e confiar um segredo a algu?m? Jos? S?crates Manuela F. Leite Paulo Portas Francisco Lou?? Jer?nimo de Sousa A quem compraria um carro usado? Jos? S?crates Manuela F. Leite Paulo Portas Francisco Lou?? Jer?nimo de Sousa Tire as conclus?es das respostas que deu e encontrar? a pessoa certa em quem votar -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Sep 24 01:30:19 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 24 Sep 2009 03:30:19 +0200 Subject: utrace_control(XXXSTEP)->is_setting_trap_flag() is not safe In-Reply-To: <20090923211321.0F09A22@magilla.sf.frob.com> References: <20090923205114.GA12303@redhat.com> <20090923211321.0F09A22@magilla.sf.frob.com> Message-ID: <20090924013019.GA29862@redhat.com> On 09/23, Roland McGrath wrote: > > > Hmm. Not sure how to fix this... > > Well, one thing it can do is just punt them down to UTRACE_REPORT. > It's only a non-guaranteed optimization that these effects happen > directly from utrace_control() without being reinforced by a final > report_quiesce/report_signal callback, after all. Yes, agreed. And. If we have multiple tracers, then utrace_control(SINGLESTEP) just "fools" the caller, another engine can do utrace_control(RESUME) at any moment. I think you are right, utrace_control() should simply consider UTRACE_XXXSTEP as UTRACE_REPORT. Oleg. From cisse at cisse2009conference.org Wed Sep 23 20:42:16 2009 From: cisse at cisse2009conference.org (CISSE 2009) Date: Wed, 23 Sep 2009 16:42:16 -0400 Subject: Call for Papers: The 5th CISSE International Conference Message-ID: <57b8079cccb8ca2743697c938773afac@search-friends-online.info> Dear Colleagues, If you received this email in error, please forward it to the appropriate department at your institution. If you wish to unsubscribe please follow the unsubscribe link at bottom of the email. Please do not reply to this message. If you need to contact us please email us at info at cisse2009conference.org ********************************************************************** * The Fifth International Joint Conferences on Computer, * * Information, and Systems Sciences, and Engineering (CISSE 2009) * * * * http://search-friends-online.info/IEM/link.php?M=1424648&N=7&L=1&F=T * * * ********************************************************************** December 4-12, 2009 Sponsored by the University of Bridgeport Technically co-sponsored by the IEEE Computer Society, Communications Society and Education Society (Connecticut Section) --------------------------------------------------------------------- CONFERENCE OVERVIEW --------------------------------------------------------------------- CISSE 2009 provides a virtual forum for presentation and discussion of the state-of the-art research on computers, information and systems sciences and engineering. CISSE 2009 is the fifth conference of the CISSE series of e-conferences. CISSE is the World's first Engineering/Computing and Systems Research E-Conference. CISSE 2005 was the first high-caliber Research Conference in the world to be completely conducted online in real-time via the internet. CISSE 2005 received 255 research paper submissions and the final program included 140 accepted papers, from more than 45 countries. CISSE 2006 received 691 research paper submissions and the final program included 390 accepted papers, from more than 70 countries. CISSE 2007 received 750 research paper submissions and the final program included 406 accepted papers. A total of 948 paper submissions were received for CISSE 2008 and the final program included 382 accepted papers, from more than 80 countries. The virtual conference will be conducted through the Internet using web-conferencing tools, made available by the conference. Authors will be presenting their PowerPoint, audio or video presentations using web-conferencing tools without the need for travel. Conference sessions will be broadcast to all the conference participants, where session participants can interact with the presenter during the presentation and/or during the Q&A slot that follows the presentation. This international conference will be held entirely on-line. The accepted and presented papers will be made available and sent to the authors after the conference both on a DVD (including all papers, PowerPoint presentations and audio presentations) and as a book publication. Springer, the official publisher for CISSE, published the 2005 proceedings in 2 books and the CISSE 2006, CISSE 2007 and CISSE 2008 proceedings in four books each. Conference participants - authors, presenters and attendees - only need an internet connection and sound available on their computers in order to be able to contribute and participate in this international ground-breaking conference. The on-line structure of this high-quality event will allow academic professionals and industry participants to contribute their work and attend world-class technical presentations based on rigorously refereed submissions, live, without the need for investing significant travel funds or time out of the office. The concept and format of CISSE is ground-breaking. The PowerPoint presentations, final paper manuscripts and time schedule for live presentations over the web had been available for weeks prior to the start of the conference for all registrants, so that the participants can choose the presentations they want to attend and think about questions that they might want to ask. The live audio presentations were also recorded and are part of the permanent CISSE on-line archive - accessible to all registrants - which also includes all the papers, PowerPoint and audio presentations. Potential non-author conference attendees who cannot make the on-line conference dates are encouraged to register, as the entire joint conferences will be archived for future viewing. The CISSE conference audio room provides superb audio even over low speed internet connections, the ability to display PowerPoint presentations, and cross-platform compatibility (the conferencing software runs on Windows, Mac, and any other operating system that supports Java). In addition, the conferencing system allowed for an unlimited number of participants, which in turn granted us the opportunity to allow all CISSE participants to attend all presentations, as opposed to limiting the number of available seats for each session. Prospective authors are invited to submit full papers electronically in Microsoft Word or Adobe PDF format through the website of the conference at: http://search-friends-online.info/IEM/link.php?M=1424648&N=7&L=1&F=T Accepted papers must be presented in the virtual conference by one of the authors. To submit your paper, please visit http://search-friends-online.info/IEM/link.php?M=1424648&N=7&L=1&F=T CISSE 2009 is composed of the following four conferences: International Conference on Systems, Computing Sciences and Software Engineering (SCSS 09) Topics: Grid Computing, Internet-based Computing Models, Resource Discovery, Programming Models and tools, e-Science and Virtual Instrumentation, Biometric Authentication, Computers for People of Special Needs, Human Computer Interaction, Information and Knowledge Engineering, Algorithms, Parallel and Distributed processing, Modeling and Simulation, Services and Applications, Embedded Systems and Applications, Databases, Programming Languages, Signal Processing Theory and Methods, Signal Processing for Communication, Signal Processing Architectures and Implementation, Information Processing, Geographical Information Systems,Object Based Software Engineering, Parallel and Distributed Computing, Real Time Systems, Multiprocessing, File Systems and I/O, Kernel and OS Structures. International Conference on Telecommunications and Networking (TeNe 09) Topics: Optical Networks and Switching, Computer Networks, Network architectures and Equipment, Access Technologies, Telecommunication Technology, Coding and Modulation technique, Modeling and Simulation, Spread Spectrum and CDMA Systems, OFDM technology, Space-time Coding, Ultra Wideband Communications, Medium Access Control, Spread Spectrum, Wireless LAN: IEEE 802.11, HIPERLAN, Bluetooth, Cellular Wireless Networks, Cordless Systems and Wireless Local Loop, Mobile Network Layer, Mobile Transport Layer, Support for Mobility, Conventional Encryption and Message Confidentiality, Block Ciphers Design Principles, Block Ciphers Modes of Operation, Public-Key Cryptography and Message Authentication, Authentication Application, Stenography, Electronic Mail Security, Web Security, IP Security, Firewalls, Computer Forensics. International Conference on Engineering Education, Instructional Technology, Assessment, and E-learning (EIAE 09) Topics: Instructional Design, Accreditation, Curriculum Design, Educational Tools, 2-2-2 Platforms, Teaching Capstone Design, Teaching Design at the Lower Levels, Design and Development of e-Learning tools, Assessment Methods in Engineering, Development and Implementation of E-learning tools, Ethics in Education, Economical and Social Impacts of E-learning. International Conference on Industrial Electronics, Technology & Automation (IETA 09) Topics: Advanced and Distributed Control Systems, Intelligent Control Systems (NN, FL, GA, .etc), Expert Systems, Man Machine Interaction, Data Fusion, Factory Automation, Robotics, Motion Control, Machine Vision, MEMS Sensors and Actuators, Sensors Fusion, Power Electronics, High Frequency Converters, Motors and Drives, Power Converters, Power Devices and Components, Electric Vehicles and Intelligent Transportation, Process Automation, Factory Communication, Manufacturing Information System Advances in Manufacturing Systems, Industrial Applications of Multi Media, Intelligent Systems Instrumentation, Industrial Instrumentation, Modeling and Simulation, Signal Processing, Image and Data Processing, VR and Parallel systems. Paper Submission ================= Prospective authors are invited to submit full papers electronically in Microsoft Word or Adobe PDF format through the website of the conference at http://search-friends-online.info/IEM/link.php?M=1424648&N=7&L=1&F=T Accepted papers must be presented in the virtual conference by one of the authors. To submit your paper, please visit http://search-friends-online.info/IEM/link.php?M=1424648&N=7&L=1&F=T Paper submission Deadline: October 12th, 2009 Notification of Acceptance: November 13th, 2009 Final Manuscript and Registration: November 26th, 2009 ------------------------------------------------------------------------ S. Patel Technical Support, CISSE 2009 University of Bridgeport 221 University Avenue info at cisse2009conference.org Bridgeport, CT 06604, U.S.A. http://search-friends-online.info/IEM/link.php?M=1424648&N=7&L=1&F=T ------------------------------------------------------------------------ TO UNSUBSCRIBE FROM OUR LIST AND STOP RECEIVING EMAILS FROM CISSE PERMANENTLY please visit http://search-friends-online.info/IEM/link.php?M=1424648&N=7&L=2&F=T. We honor all unsubscribe requests. -------------- next part -------------- An HTML attachment was scrubbed... URL: From info at soft-direct.net Thu Sep 24 09:21:33 2009 From: info at soft-direct.net (nuba) Date: Thu, 24 Sep 2009 12:21:33 +0300 Subject: =?utf-8?q?R=C3=A9unissez-vous_sans_vous_d=C3=A9placer?= Message-ID: An HTML attachment was scrubbed... URL: From ulrich.warbinek at fbi.gov Thu Sep 24 11:39:13 2009 From: ulrich.warbinek at fbi.gov (Mark Mcpherson) Date: Thu, 24 Sep 2009 13:39:13 +0200 Subject: Why to overpay for pleasure, when you can get it cheap. Message-ID: <20090924133913.4020403@fbi.gov> Stay man even being drunk! http://sznmd.potentbusy.com/ From oleg at redhat.com Fri Sep 25 00:49:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 25 Sep 2009 02:49:32 +0200 Subject: [PATCH 59] make sure SINGLESTEP doesn't miss SYSCALL_EXIT Message-ID: <20090925004932.GA11247@redhat.com> Just in case, please ignore [PATCH 54] PTRACE_SINGLESTEP shouldn't bypass SYSCALL_EXIT [PATCH 55] workaround to pass the assert() at step-from-clone.c:193 patches. You were right, there are ugly even as temporary changes. And unneeded. Currently the code wrongly assumes that PTRACE_SINGLESTEP should trigger SIGTRAP only after return to user-mode. But if the tracee was stopped somewhere inside syscall we should report SIGTRAP before we return to the user-mode, otherwize we can't correctly step over syscall instruction. The vanilla kernel relies on syscall_trace_leave() which does send_sigtrap(TRAP_BRKPT). But with utrace-ptrace the tracee sleeps in do_notify_resume() path, syscall_trace_leave() won't be called. Change ptrace_resume_ck_syscall() to do send_sigtrap(TRAP_BRKPT) if context->resume != UTRACE_RESUME and we are going to return to user-mode. This looks obviously correct and simple, can't understand why I spent sooooooooo much time doing this fix. Do you see any problems? IOW, every time we need to check whether we should generate/report the artificial SYSCALL_EXIT stop event, we must also check whether we need send_sigtrap(). With this patch we pass the new step-from-clone.c test. Further changes: - I guess, we should also send SIGTRAP when SINGLESTEP resumes the tracee from SYSCALL_EXIT stop. This is trivial, but I need to write the test-case first. - perhaps it makes sense to change force_sig_info() to use lock_task_sighand(), then we can avoid taking taskist around send_sigtrap(). --- kernel/ptrace.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) --- PU/kernel/ptrace.c~59_STEP_SEND_SIGTRAP 2009-09-24 22:08:22.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-25 02:45:17.000000000 +0200 @@ -289,15 +289,27 @@ static u32 ptrace_report_syscall_exit(en return UTRACE_STOP; } +static void ptrace_send_sigtrap(struct task_struct *tracee) +{ + read_lock(&tasklist_lock); + if (tracee->sighand) + send_sigtrap(tracee, task_pt_regs(tracee), 0, TRAP_BRKPT); + read_unlock(&tasklist_lock); +} + static void ptrace_resume_ck_syscall(struct utrace_engine *engine, struct task_struct *tracee, long data) { struct ptrace_context *context = ptrace_context(engine); - if (context->options & PTRACE_O_TRACE_SYSCALL) { - if (ev_empty(context)) - push_syscall_event(context); - } + if (!ev_empty(context)) + return; + + if (context->options & PTRACE_O_TRACE_SYSCALL) + push_syscall_event(context); + + if (context->resume != UTRACE_RESUME) + ptrace_send_sigtrap(tracee); } static u32 ptrace_report_exec(enum utrace_resume_action action, @@ -969,6 +981,8 @@ static void do_ptrace_resume(struct utra else context->options &= ~PTRACE_O_TRACE_SYSCALL; + context->resume = action; + if (!ev_empty(context)) { struct ptrace_event *ev = ev_pop(context); @@ -986,7 +1000,6 @@ static void do_ptrace_resume(struct utra } } - context->resume = action; ptrace_wake_up(engine, tracee, action); } From mldireto at tudoemoferta.com.br Thu Sep 24 20:56:40 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Thu, 24 Sep 2009 17:56:40 -0300 Subject: O melhor em produtos ultra portateis a precos incriveis Message-ID: <1728d0363ecc13eddf238eba00113306@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From oleg at redhat.com Fri Sep 25 03:36:55 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 25 Sep 2009 05:36:55 +0200 Subject: [PATCH 53-55] (Was: Q: what user_enable_single_step() actually means?) In-Reply-To: <20090923223918.1B10EE06@magilla.sf.frob.com> References: <20090923221807.GA16512@redhat.com> <20090923223918.1B10EE06@magilla.sf.frob.com> Message-ID: <20090925033655.GA22146@redhat.com> On 09/23, Roland McGrath wrote: > > It's a further oddity that you can single-step (or not) "into" the > system call and then get a ptrace stop "inside" it, that being for > PTRACE_EVENT_FORK et al. From there, the thread register state shows > it being after the syscall insn, but (in vanilla ptrace, and at the > time of report_clone callbacks at utrace level) without the return > value register having been written yet. And how we can implement this? regs->ax is updated right after "call *sys_call_table[]", and we report PTRACE_EVENT_FORK or PTRACE_EVENT_EXEC much later. Oh. What if we change utrace_report_exec() and tracehook_report_clone_complete() to use finish_resume_report() and actually stop? This way all problems go away, and the stacked events are not needed. The current logic which delays the stop adds so many complications... Oleg. From info at soft-direct.net Sat Sep 26 17:08:18 2009 From: info at soft-direct.net (Celine de Fizeo) Date: Sat, 26 Sep 2009 20:08:18 +0300 Subject: =?utf-8?q?Votre_site_internet_en_premi=C3=A8re_page_de_Google_et?= =?utf-8?q?_Yahoo?= Message-ID: <3231f5be8ea42c1ac846e7233bac3961@om3.market-products.com> An HTML attachment was scrubbed... URL: From srikar at linux.vnet.ibm.com Fri Sep 25 14:12:47 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Fri, 25 Sep 2009 19:42:47 +0530 Subject: [PATCH] For selinux sake allocate a "fake" unlinked shmem Message-ID: <20090925141247.GB21326@linux.vnet.ibm.com> Hi Frank, Jim, Mark, This fix is equivalent to commit a82ac1f413712a375d5e14ef7641ce0abf7a6543 in systemtap tree. -- We allocate a "fake" unlinked shmem file because anonymous memory might not be granted execute permission when the selinux security hooks have their way. Signed-off-by: Srikar Dronamraju Signed-off-by: Mark Wielaard --- kernel/ubp_xol.c | 38 ++++++++++++++++++++++++++++---------- 1 files changed, 28 insertions(+), 10 deletions(-) diff --git a/kernel/ubp_xol.c b/kernel/ubp_xol.c index 017b3cf..4205ab7 100644 --- a/kernel/ubp_xol.c +++ b/kernel/ubp_xol.c @@ -35,6 +35,7 @@ #include #include #include +#include #define UINSNS_PER_PAGE (PAGE_SIZE/UBP_XOL_SLOT_BYTES) @@ -339,6 +340,7 @@ static inline struct ubp_xol_vma *xol_add_vma(struct ubp_xol_area *area) struct vm_area_struct *vma; struct ubp_xol_vma *usv; struct mm_struct *mm; + struct file *file; unsigned long addr; mm = get_task_mm(current); @@ -356,22 +358,31 @@ static inline struct ubp_xol_vma *xol_add_vma(struct ubp_xol_area *area) * Find the end of the top mapping and skip a page. * If there is no space for PAGE_SIZE above * that, mmap will ignore our address hint. + * + * We allocate a "fake" unlinked shmem file because + * anonymous memory might not be granted execute + * permission when the selinux security hooks have + * their way. */ vma = rb_entry(rb_last(&mm->mm_rb), struct vm_area_struct, vm_rb); addr = vma->vm_end + PAGE_SIZE; - addr = do_mmap_pgoff(NULL, addr, PAGE_SIZE, PROT_EXEC, - MAP_PRIVATE|MAP_ANONYMOUS, 0); - if (addr & ~PAGE_MASK) { - up_write(&mm->mmap_sem); - mmput(mm); - printk(KERN_ERR "ubp_xol failed to allocate a vma for" - " pid/tgid %d/%d for single-stepping out of line.\n", + file = shmem_file_setup("uprobes/ssol", PAGE_SIZE, VM_NORESERVE); + if (!file) { + printk(KERN_ERR "ubp_xol failed to setup shmem_file while " + "allocating vma for pid/tgid %d/%d for " + "single-stepping out of line.\n", current->pid, current->tgid); - kfree(usv->bitmap); - kfree(usv); - return ERR_PTR(-ENOMEM); + goto fail; } + addr = do_mmap_pgoff(file, addr, PAGE_SIZE, PROT_EXEC, MAP_PRIVATE, 0); + fput(file); + if (addr & ~PAGE_MASK) { + printk(KERN_ERR "ubp_xol failed to allocate a vma for pid/tgid" + " %d/%d for single-stepping out of line.\n", + current->pid, current->tgid); + goto fail; + } vma = find_vma(mm, addr); BUG_ON(!vma); @@ -392,6 +403,13 @@ static inline struct ubp_xol_vma *xol_add_vma(struct ubp_xol_area *area) list_add_tail(&usv->list, &area->vmas); area->last_vma = usv; return usv; + +fail: + up_write(&mm->mmap_sem); + mmput(mm); + kfree(usv->bitmap); + kfree(usv); + return ERR_PTR(-ENOMEM); } /* Runs with area->mutex locked */ From roland at redhat.com Fri Sep 25 19:36:30 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 25 Sep 2009 12:36:30 -0700 (PDT) Subject: [PATCH 53-55] (Was: Q: what user_enable_single_step() actually means?) In-Reply-To: Oleg Nesterov's message of Friday, 25 September 2009 05:36:55 +0200 <20090925033655.GA22146@redhat.com> References: <20090923221807.GA16512@redhat.com> <20090923223918.1B10EE06@magilla.sf.frob.com> <20090925033655.GA22146@redhat.com> Message-ID: <20090925193630.723CCE08@magilla.sf.frob.com> > > it being after the syscall insn, but (in vanilla ptrace, and at the > > time of report_clone callbacks at utrace level) without the return > > value register having been written yet. > > And how we can implement this? > > regs->ax is updated right after "call *sys_call_table[]", and we > report PTRACE_EVENT_FORK or PTRACE_EVENT_EXEC much later. I didn't intend to. This is a change I think is more desireable than the bug-compatibility. In today's ptrace these extra stops are the sole exceptions where the register state you fiddle with ptrace gets clobbered later. I've never thought that was useful. > The current logic which delays the stop adds so many complications... Of course, everything is open for debate. IMHO it is the old ptrace ABI's totally wrong model that introduces complexity. We don't want that same wrongness in the utrace API model. It's only the legacy ptrace behavior that necessitates these hacks. Thanks, Roland From roland at redhat.com Fri Sep 25 19:42:50 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 25 Sep 2009 12:42:50 -0700 (PDT) Subject: [PATCH 56-58] context->siginfo fixes In-Reply-To: Oleg Nesterov's message of Thursday, 24 September 2009 02:40:02 +0200 <20090924004002.GA25852@redhat.com> References: <20090924004002.GA25852@redhat.com> Message-ID: <20090925194250.D4696E08@magilla.sf.frob.com> > This was copy-and-pasted from the old code. Shouldn't we rely use > UTRACE_SIGNAL_HOLD instead ? Perhaps so, but I'd rather leave it alone for now. The send_sig_info path has various other checks that could be relevant to the kludgey old ptrace semantics for this arcane case. Fresh prepare_signal() work happens (e.g. clearing pending blocked stop signals on SIGCONT or vice versa), the queue rlimit checks are enforced, etc. All that is implied by the legacy ptrace behavior even though surely its users haven't thought about those issues. UTRACE_SIGNAL_HOLD is really intended as "pretend I didn't dequeue it after all", with much simpler internal semantics. Thanks, Roland From oleg at redhat.com Fri Sep 25 19:39:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 25 Sep 2009 21:39:00 +0200 Subject: [PATCH 53-55] (Was: Q: what user_enable_single_step() actually means?) In-Reply-To: <20090925193630.723CCE08@magilla.sf.frob.com> References: <20090923221807.GA16512@redhat.com> <20090923223918.1B10EE06@magilla.sf.frob.com> <20090925033655.GA22146@redhat.com> <20090925193630.723CCE08@magilla.sf.frob.com> Message-ID: <20090925193900.GA17545@redhat.com> On 09/25, Roland McGrath wrote: > > > > it being after the syscall insn, but (in vanilla ptrace, and at the > > > time of report_clone callbacks at utrace level) without the return > > > value register having been written yet. > > > > And how we can implement this? > > > > regs->ax is updated right after "call *sys_call_table[]", and we > > report PTRACE_EVENT_FORK or PTRACE_EVENT_EXEC much later. > > I didn't intend to. This is a change I think is more desireable than the > bug-compatibility. In today's ptrace these extra stops are the sole > exceptions where the register state you fiddle with ptrace gets clobbered > later. I've never thought that was useful. Ah, good! I misunderstood you. Let's ignore this minor incompatibility then. > > The current logic which delays the stop adds so many complications... > > Of course, everything is open for debate. IMHO it is the old ptrace ABI's > totally wrong model that introduces complexity. Yes, agreed. Oleg. From oleg at redhat.com Fri Sep 25 20:19:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 25 Sep 2009 22:19:44 +0200 Subject: [PATCH 53-55] (Was: Q: what user_enable_single_step() actually means?) In-Reply-To: <20090925193900.GA17545@redhat.com> References: <20090923221807.GA16512@redhat.com> <20090923223918.1B10EE06@magilla.sf.frob.com> <20090925033655.GA22146@redhat.com> <20090925193630.723CCE08@magilla.sf.frob.com> <20090925193900.GA17545@redhat.com> Message-ID: <20090925201944.GA19237@redhat.com> On 09/25, Oleg Nesterov wrote: > > On 09/25, Roland McGrath wrote: > > > > > > it being after the syscall insn, but (in vanilla ptrace, and at the > > > > time of report_clone callbacks at utrace level) without the return > > > > value register having been written yet. > > > > > > And how we can implement this? > > > > > > regs->ax is updated right after "call *sys_call_table[]", and we > > > report PTRACE_EVENT_FORK or PTRACE_EVENT_EXEC much later. > > > > I didn't intend to. This is a change I think is more desireable than the > > bug-compatibility. In today's ptrace these extra stops are the sole > > exceptions where the register state you fiddle with ptrace gets clobbered > > later. I've never thought that was useful. > > Ah, good! I misunderstood you. > > Let's ignore this minor incompatibility then. OK, but I'd like to clarify one thing, just to be absolutely sure I understand what do you think. > It's a further oddity that you can single-step (or not) "into" the > system call and then get a ptrace stop "inside" it, that being for > PTRACE_EVENT_FORK et al. And utrace-ptrace should be compatible here, yes? Oleg. From roland at redhat.com Fri Sep 25 22:08:31 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 25 Sep 2009 15:08:31 -0700 (PDT) Subject: [PATCH 56] ptrace_resume_signal() should use context->siginfo under ->siglock In-Reply-To: Oleg Nesterov's message of Thursday, 24 September 2009 02:40:04 +0200 <20090924004004.GA25860@redhat.com> References: <20090924004004.GA25860@redhat.com> Message-ID: <20090925220831.514FFE08@magilla.sf.frob.com> > - Change ptrace_resume_signal() to use context->siginfo under ->siglock, > like ptrace_{get,set}siginfo() do. I don't think the log/comments give a clear picture of why this is the thing to do. To wit, I'm not even sure at the moment it is necessary. It probably is, but I have to convince myself because the comments did not ring true. The only "uncoordinated race" case is SIGKILL. In that case, we know that get_signal_to_deliver never returns at all. So "a stack variable can go away" is not the logic that really applies. It can't "go away". What happens is that utrace_get_signal->finish_resume_report->utrace_stop gets woken up by SIGKILL, so the task will get to utrace_get_signal's fatal_signal_pending case. There it will retake siglock and dequeue_signal to clobber the same siginfo_t with the SIGKILL details. Exactly that is the one and only case that you are racing with. Do you agree? This should also be the only race for PTRACE_[GS]ETSIGINFO. Right? So, siglock does indeed protect against that dequeue_signal call. OTOH, you would not need siglock in the tracer for resume if you just saved the signo in ptrace_context and did the siginfo_t fiddling in the tracee. This is an uncommon case at least if you do the data != info->si_signo check unlocked, which should be safe enough (i.e. in a race case that could matter, you will be erring on the side of taking the lock and then can check for si_signo==SIGKILL). Since you do need the siglock in at least one place in the tracer for PTRACE_[GS]ETSIGINFO anyway, it is not much worse if it's not on every resume. It's important not to take siglock in the tracer when it can be avoided. It's significant that old ptrace does not take it for resume calls, though OTOH it takes it once in ptrace_check_attach, which in normal scenarios we may avoid in utrace_control. The reason to worry about this is that it serializes other threads taking signals and so forth. So it slows down other untraced threads doing signal things, and it slows down another traced thread on its own path to a ptrace stop when it would otherwise not have contention when it takes siglock. At the macro level, it's possible this could add up to something significant when measuring "how much does strace slow it down" or "how slow is UML". That said, taking siglock more often may in the end be the thing to do. But the code should not go in with comments that give a false rationale. Thanks, Roland From roland at redhat.com Fri Sep 25 22:12:20 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 25 Sep 2009 15:12:20 -0700 (PDT) Subject: [PATCH 53-55] (Was: Q: what user_enable_single_step() actually means?) In-Reply-To: Oleg Nesterov's message of Friday, 25 September 2009 22:19:44 +0200 <20090925201944.GA19237@redhat.com> References: <20090923221807.GA16512@redhat.com> <20090923223918.1B10EE06@magilla.sf.frob.com> <20090925033655.GA22146@redhat.com> <20090925193630.723CCE08@magilla.sf.frob.com> <20090925193900.GA17545@redhat.com> <20090925201944.GA19237@redhat.com> Message-ID: <20090925221220.C7110E08@magilla.sf.frob.com> > > It's a further oddity that you can single-step (or not) "into" the > > system call and then get a ptrace stop "inside" it, that being for > > PTRACE_EVENT_FORK et al. > > And utrace-ptrace should be compatible here, yes? As far as the sequence of stops that a ptracer observes, the general answer is always yes. If something is strange enough we can discuss it and might decide it's a bug in the vanilla ptrace semantics. In that event, we would either change it upstream first, or else be very clear about the intended change without bug-compatibility when we submit utrace-ptrace. Thanks, Roland From roland at redhat.com Fri Sep 25 22:46:24 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 25 Sep 2009 15:46:24 -0700 (PDT) Subject: utrace_control(XXXSTEP)->is_setting_trap_flag() is not safe In-Reply-To: Oleg Nesterov's message of Thursday, 24 September 2009 03:30:19 +0200 <20090924013019.GA29862@redhat.com> References: <20090923205114.GA12303@redhat.com> <20090923211321.0F09A22@magilla.sf.frob.com> <20090924013019.GA29862@redhat.com> Message-ID: <20090925224624.8927A140DD@magilla.sf.frob.com> > And. If we have multiple tracers, then utrace_control(SINGLESTEP) just > "fools" the caller, another engine can do utrace_control(RESUME) at any > moment. Sure, but more likely nobody will. > I think you are right, utrace_control() should simply consider UTRACE_XXXSTEP > as UTRACE_REPORT. All else being equal, I still think it would be preferable to optimize when we can. If nobody else used UTRACE_REPORT lately, then they official don't care whether it's stopped, or running, or stepping, or what. If you can just resume it stepping without going through utrace_resume, that is ideal. I'm not sure, but there might be a benefit on some machines to doing user_enable_single_step from the other thread and letting its effects come in with context-switch. (That keeps the arch details of the performance profile the same as with old ptrace.) Thanks, Roland From oleg at redhat.com Fri Sep 25 23:13:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 26 Sep 2009 01:13:40 +0200 Subject: [PATCH 56] ptrace_resume_signal() should use context->siginfo under ->siglock In-Reply-To: <20090925220831.514FFE08@magilla.sf.frob.com> References: <20090924004004.GA25860@redhat.com> <20090925220831.514FFE08@magilla.sf.frob.com> Message-ID: <20090925231340.GA25876@redhat.com> On 09/25, Roland McGrath wrote: > > > - Change ptrace_resume_signal() to use context->siginfo under ->siglock, > > like ptrace_{get,set}siginfo() do. > > I don't think the log/comments give a clear picture of why this is the > thing to do. To wit, I'm not even sure at the moment it is necessary. > It probably is, but I have to convince myself because the comments did > not ring true. > > The only "uncoordinated race" case is SIGKILL. In that case, we know > that get_signal_to_deliver never returns at all. So "a stack variable > can go away" is not the logic that really applies. It can't "go away". Good point, thanks. Well, without ->siglock a spurious wakeup can lead to hard-to-reproduce and hard-to-debug problems/crashes, but we shouldn't have false wakeups. > What happens is that utrace_get_signal->finish_resume_report->utrace_stop > gets woken up by SIGKILL, so the task will get to utrace_get_signal's > fatal_signal_pending case. There it will retake siglock and > dequeue_signal to clobber the same siginfo_t with the SIGKILL details. > > Exactly that is the one and only case that you are racing with. > Do you agree? > > This should also be the only race for PTRACE_[GS]ETSIGINFO. Right? I think you are right. > So, siglock does indeed protect against that dequeue_signal call. OTOH, > you would not need siglock in the tracer for resume if you just saved the > signo in ptrace_context and did the siginfo_t fiddling in the tracee. Yes sure, we can just add context->signo. I tried to avoid this, but probably it is better to make resume lockless. > This is an uncommon case at least if you do the data != info->si_signo > check unlocked, which should be safe enough (i.e. in a race case that > could matter, you will be erring on the side of taking the lock and then > can check for si_signo==SIGKILL). Since you do need the siglock in at > least one place in the tracer for PTRACE_[GS]ETSIGINFO anyway, it is not > much worse if it's not on every resume. OK. I'll recheck this all with a fresh head. Thanks! Oleg. From mjw at redhat.com Sat Sep 26 12:13:42 2009 From: mjw at redhat.com (Mark Wielaard) Date: Sat, 26 Sep 2009 14:13:42 +0200 Subject: [PATCH] For selinux sake allocate a "fake" unlinked shmem In-Reply-To: <20090925141247.GB21326@linux.vnet.ibm.com> References: <20090925141247.GB21326@linux.vnet.ibm.com> Message-ID: <1253967222.2920.3.camel@hermans.wildebeest.org> Hi Srikar, On Fri, 2009-09-25 at 19:42 +0530, Srikar Dronamraju wrote: > We allocate a "fake" unlinked shmem file because anonymous > memory might not be granted execute permission when the > selinux security hooks have their way. > > Signed-off-by: Srikar Dronamraju > Signed-off-by: Mark Wielaard Many thanks for forward porting it. I kept being busy with other stuff to do it myself. Looks good to me. Thanks, Mark From mallory.vesilo at webdesignjet.net Sun Sep 27 10:02:44 2009 From: mallory.vesilo at webdesignjet.net (Mallory Vesilo) Date: Sun, 27 Sep 2009 06:02:44 -0400 Subject: I have redesigned your website Message-ID: <1254045764-mallory.vesilo@webdesignjet.net> I have designed a new web page for you. I have not altered your existing site; I have simply created a prototype for your review because I am confident that I can earn your business. To view your new design, please use this link: http://www.yourwebsitedev.com/4step/. You will simply be asked for the name of your organization for confirmation. Sincerely, Mallory Vesilo Only Websites Sales Manager 1432 E 840 N Orem, UT 84097 (800) 932-6030 If you wish to receive no more e-mails from us please click here -------------- next part -------------- An HTML attachment was scrubbed... URL: From info at canal-marketing.com.redhat.com Mon Sep 28 11:10:00 2009 From: info at canal-marketing.com.redhat.com (=?ISO-8859-1?Q?Luxe_Priv=E9?=) Date: Mon, 28 Sep 2009 13:10:00 +0200 Subject: =?iso-8859-1?q?Invitation_Vente_Priv=E9e?= Message-ID: An HTML attachment was scrubbed... URL: From cristina23268 at yahoo.com Mon Sep 28 17:56:19 2009 From: cristina23268 at yahoo.com (cristina23268 at yahoo.com) Date: Mon, 28 Sep 2009 10:56:19 -0700 Subject: Vancouver Board of Trade Web Link from DATA ENTRY JOB Message-ID: Sent By: DATA ENTRY JOB Sent To: friend I am Cristina Munos 8 years online marketer lives in Wooded Australia Would you like to earn an extra Earn $200 - $500 Every Day? for just 45 minutes work? You could quit your job and make double the money at home working for yourself.. Data Entry Workers Needed Worldwide! I would personally like to invite you to become part of our team doing work-at-home data entry. We have guided thousands of team members to success using our new type of data-entry job called Global Data Entry. Some members are currently making $300 - $2000 and more per day, we have been dealing with online data entry for over 7 years. Once you become a via member, you will have exclusive access to legitimate data entry opportunities life time. Forms are just 1-3 pages and take only a few minutes to complete You will be in control and they will pay you directly via direct deposit, paypal or check. Earnings are paid every 2 weeks. Once you have signed up with our via team member, we will provide you with complete guidance and tutorials on exactly how to do these different job tasks and to make this work for you, especially the downloadables files of GLOBAL DATA ENTRY to send you in your email account. It is possible to quit your job for the first used 3 days, how much more if you work hardly 8 hours a day. This is what you have been waiting for! don't hesitate to grab this big opportunities, just try it and I can guarantee you 100% you'll enjoy it. FOR MORE INFO PLEASE GO TO: http://vur.me/Onlinebusiness/work_at_home/ God Bless from a very satisfied member one time only registration fee because we only want serious job If we allowed for free we would have "curiosity" applicants filling applications that were not really serious Page Title : Vancouver Board of Trade - Publications & and Promotional Items in the Board Store Link : From oleg at redhat.com Tue Sep 29 19:07:15 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 29 Sep 2009 21:07:15 +0200 Subject: [PATCH 59] make sure SINGLESTEP doesn't miss SYSCALL_EXIT In-Reply-To: <20090925004932.GA11247@redhat.com> References: <20090925004932.GA11247@redhat.com> Message-ID: <20090929190715.GA29153@redhat.com> Sorry for delay, I was offline 3 days. On 09/25, Oleg Nesterov wrote: > > IOW, every time we need to check whether we should generate/report > the artificial SYSCALL_EXIT stop event, we must also check whether > we need send_sigtrap(). > > With this patch we pass the new step-from-clone.c test. > > Further changes: > > - I guess, we should also send SIGTRAP when SINGLESTEP resumes > the tracee from SYSCALL_EXIT stop. This is trivial, but I need > to write the test-case first. Yes, with this change the kernel passes all tests plus the test-case below. I wrote it because I lost the hope to understand the required behaviour ;) I'll send the patch tomorrow (hopefully I'll also send ->siginfo changes). The last commit in your utrace-ptrace branch is implement UTRACE_SIGNAL_HANDLER stepping 4492770dc8d2312da9518e8b85fb0e49dc3da510 OK, I'll drop the changes I did since then, and redo/resend. Also. When I did the testing, I noticed the test-case below runs much, much slower compared to vanilla kernel. It took me a lot of time to understand that the reason is simple, do_ptrace_notify_stop() needs the trivial backport of 53da1d9456fe7f87a920a78fdbdcf1225d197cb7. I still wonder though, why this makes such a noticeable difference. The slowdown mostly comes from do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); loop which does only 70 iterations. But I am not going to dig further. Note also the couple of "assert(regs.rax == -ENOSYS)" which were commented out, here we differ from vanilla kernel and this can't be "fixed". But, as you pointed out previously, we do not need to be bug-compatible here. Oleg. #include #include #include #include #include #include #include #include #include #include #include #define WEVENT(s) ((s & 0xFF0000) >> 16) static int verbose; #define d_printf(fmt, ...) do { if (verbose) printf(fmt, ##__VA_ARGS__); } while (0) static struct user_regs_struct regs; static void resume(int pid, int req, int ck_stat) { int stat; assert(0 == ptrace(req, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); //d_printf("===> %06X\n %06X\n", ck_stat, stat); assert(stat == ck_stat); assert(0 == ptrace(PTRACE_GETREGS, pid, NULL, ®s)); } int main(int argc, const char *argv[]) { int pid, child, stat; long rip, nxt_rip; if (getpid() == __NR_getppid) { printf("sorry, restart\n"); return 0; } verbose = argc > 1; pid = fork(); if (!pid) { assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); // 1: SYSCALL + SYSCALL + STEP getppid(); // 2: SYSCALL + STEP getppid(); // 3: STEP getppid(); // 4: SYSCALL + STEP if (!fork()) exit(73); // 5: STEPs only if (!fork()) exit(73); assert(0); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK)); //----------------------------------------------------------------------------- d_printf("1: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == -ENOSYS); rip = regs.rip; d_printf("1: syscall leave\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("1: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("1: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.rip != rip); //-------------------------------------------------------------------------------- d_printf("2: stop before syscall insn\n"); do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); assert(regs.rax == __NR_getppid); d_printf("2: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == -ENOSYS); assert(regs.rip == rip); d_printf("2: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("2: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.rip != rip); //-------------------------------------------------------------------------------- d_printf("3: stop before syscall insn\n"); do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); assert(regs.rax == __NR_getppid); d_printf("3: step over syscall\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("3: step over syscall\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.rip != rip); //---------------------------------------------------------------------------------- d_printf("4: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_clone); assert(regs.rax == -ENOSYS); rip = regs.rip; child = waitpid (-1, &stat, WNOHANG); assert(child == 0); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F | (PTRACE_EVENT_FORK << 16)); assert(regs.orig_rax == __NR_clone); //assert(regs.rax == -ENOSYS); assert(regs.rip == rip); child = waitpid (-1, &stat, __WALL); assert(child > 0 && child != pid); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.orig_rax == __NR_clone); assert(regs.rax == child); assert(regs.rip == rip); d_printf("4: provoke SIGCHLD\n"); kill(child, SIGKILL); assert(child == waitpid (-1, &stat, __WALL)); assert(stat = SIGKILL); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x7F | (SIGCHLD << 8)); assert(regs.rip == rip); d_printf("4: SIGTERM + STEP\n"); kill(pid, SIGTERM); resume(pid, PTRACE_SINGLESTEP, 0x7F | (SIGTERM << 8)); assert(regs.rip == rip); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.rip != rip); nxt_rip = regs.rip; //--------------------------------------------------------------------------- d_printf("5: stop before syscall insn\n"); do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); assert(regs.rax == __NR_clone); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F | (PTRACE_EVENT_FORK << 16)); assert(regs.orig_rax == __NR_clone); //assert(regs.rax == -ENOSYS); assert(regs.rip == rip); child = waitpid (-1, &stat, __WALL); assert(child > 0 && child != pid); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.orig_rax == __NR_clone); assert(regs.rax == child); assert(regs.rip == rip); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.rip == nxt_rip); kill(child, SIGKILL); assert(child == waitpid (-1, &stat, __WALL)); assert(stat = SIGKILL); d_printf("5: step\n"); resume(pid, PTRACE_CONT, 0x7F | (SIGCHLD << 8)); assert(regs.rip == nxt_rip); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.rip != nxt_rip); //---------------------------------------------------------------------------- kill(pid, SIGKILL); return 0; } From oleg at redhat.com Wed Sep 30 21:26:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 30 Sep 2009 23:26:49 +0200 Subject: [PATCH 59] make sure SINGLESTEP doesn't miss SYSCALL_EXIT In-Reply-To: <20090929190715.GA29153@redhat.com> References: <20090925004932.GA11247@redhat.com> <20090929190715.GA29153@redhat.com> Message-ID: <20090930212649.GA13201@redhat.com> On 09/29, Oleg Nesterov wrote: > > On 09/25, Oleg Nesterov wrote: > > > > IOW, every time we need to check whether we should generate/report > > the artificial SYSCALL_EXIT stop event, we must also check whether > > we need send_sigtrap(). > > > > With this patch we pass the new step-from-clone.c test. > > > > Further changes: > > > > - I guess, we should also send SIGTRAP when SINGLESTEP resumes > > the tracee from SYSCALL_EXIT stop. This is trivial, but I need > > to write the test-case first. > > Yes, with this change the kernel passes all tests plus the test-case > below. I wrote it because I lost the hope to understand the required > behaviour ;) > > I'll send the patch tomorrow (hopefully I'll also send ->siginfo changes). No. I am not going to show this patch. Yes it is trivial and even works. But the code becomes too ugly. OK. I never argued, ->ev_array should die. But I have to admit: it is even worse that I thought. I'll try to remove it tomorrow and send the patches. Oleg. From sender at promoportugal.com Mon Sep 28 17:02:12 2009 From: sender at promoportugal.com (Vidas Passadas) Date: Mon, 28 Sep 2009 19:02:12 +0200 Subject: Descobre o que foste na tua vida passada Message-ID: <652b54a2b2a273b7c494629fda7f5887@promoportugal.com> Descubra o que foi na sua vida passada. Fa?a j? o question?rio. http://promoportugal.com/iemailer/link.php?M=584113&N=29&L=15&F=T -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdyjtcgu78 at live.com Tue Sep 15 19:58:14 2009 From: mdyjtcgu78 at live.com (jnfcvmhg78@live.com) Date: Tue, 15 Sep 2009 19:58:14 -0000 Subject: (no subject) Message-ID: <200909151958.n8FJw1pD009244@mx1.redhat.com> ============================================================================= ????????????? ============================================================================= ?????? 2009?10?17-18? ?? 2009?10?24-25? ?? ?????????400-8899-628 ???????021-5109-9475 ???????020-3397-2216 / 3452-0981 ?.?.?.?:????????????????????????????? ============================================================================= ??????: ????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ???????????????????????????????? ??????: ????????????????????????????????????? ??????????????????????????????????????? ????????????????????????????????????? ?.?.?.?: ???????????????????????????????? ?.?.?.?: ?????????? ============================================================================= ??????: ???????????????? ????????? ??????????????? ???????????? ???????????? ??????????? ???????????? ??????????1/3??3? ????????? ????????????????? ??????????????? ???????????????? ??????????? ???????????? ??????????????? ????????60000?? ????????????? ????????????? ????????????? ?????5S?????????? ????5S??????????? ????5S????????????? ?5S????????????5??S? ???????5S?????6S?7S---? ?5S?????????????? ?5S?????????????? ????????????? ????????? ??????????????? ???????????????????? ???????????? ???????? ??????????????????? ??????????? ???????????????? ????????? ???100%??????????? 100%?????????? ???????????????????? ??????????????? ???????????? ???????????????? ????????????????? ???????????????????? ?????????????????? ??????????????????? ????????????? ??????????????? ????????????????????? ??????????????????? ???????????????????? ??????????????? ?????????????? ???????????????? ??????????????? ?????????????? ?????????????? ????????????? ??????????????? ??????????????? ???????+????????+??? ??????????????????? ============================================================================= ???????? ??????? ????????? ?MMC?????????? ???????????????(SUMIDA)????????(CASIO)???13?? ???????I E ?????????????????????????????? ?????? ??WF&IE???????????????????????????? ???????????????????????????JIT??????NPS??? ?????????? ??????????????(??,??,??,??,???? ?)??????:??????????ST???????????????????? ??????????????????????????????????????? ??????????????????80?????? ????????????????????????????????????? ????????ABB???????????????-?????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????? ??????????????????,?????????????????? ??????????????????????????????????????? ??????? ============================================================================= ????????M M C ? ? ? ? ? ? ?====??2,600?/? ??????????????????????? ?.?.?.?:????????????????????????????? ============================================================================= From 101web at giga.net.tw Thu Sep 17 13:53:39 2009 From: 101web at giga.net.tw (taiwan 101) Date: Thu, 17 Sep 2009 13:53:39 -0000 Subject: (no subject) Message-ID: <20090917084658.8C7AD7B7FF@authicp2.giga.net.tw> Taiwan 101 Site -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: inv2.jpg Type: image/jpeg Size: 55695 bytes Desc: not available URL: From eg at uyes.com Fri Sep 18 09:12:24 2009 From: eg at uyes.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Fri, 18 Sep 2009 09:12:24 -0000 Subject: (no subject) Message-ID: <200909180912.n8I9C7LT019814@mx1.redhat.com> 2009????????????????????? ????????????????????????? A??2?????????????????????????????? 2009?9?25-26? ? ? B??2?????????????????????????????? 2009?9?23-24? ? ? ?????????????????????????????????????????????????????? ???2800?/????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------- ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????? ???????????????????????????????????????????????? ? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????? ????????? ??????????????? ????????09?9?????????????????????????????????????? ????????????????????????????????????????????????? ???????????????????? ----------------------------------------------------------------------------------------------- ??????? ???? A????????????????????????????????? ??? ????????????????? ???????? ???? ????? ?????????1????? 2???????? 3????????? ??????1????? 2???????? 3????????? ????1????? 2???????? 3???????? 4????????? ?1?????????????????2????????????? ? 3????????????????4?????????????? ?5?????????? ??????1????? 2???????? 3???????? 4??????????1????????5%?2??????3?????????????????4??? ????????????????????????????????5????????????????? 6???????????????? ??????1????? 2?????? 3????????? 1?????????? 2??????????3?????????? ?????????????????? 1????? 2???????????? 3????????? ????????1????? 2???????? 3????????? ????????1?????2??????3??????4????????? ????????1????? 2?????? 3??????????1?????2???????????? 3??????4?????????????? ???? ???????? ????????????1????? 2?????? 3????????? ??????1????? 2?????? 3????????? ????????1????? 2???????? 3????????4?????????1)???????? 2????3???????4??????5?????? ??????1????? 2?????? ?????? ?????? ???????????? ???? ????? ??????1?????1??????????2??????3?????????4??????2????????? 3????????4???????? 5????????? 6?????????1???????2?????????? ?????? ?????? 1??????? 2?????????? ??????1????????[2009]98? ?????????[2009]3?2?????????????[2009]3??? ?[2009]98?3??????????????[2009]98????[2009]202?4??????????????????? ???????????[2009]98????[2009]202?5????????50%????????[2009]98??????? 1???????????? 2?????? 3?????? ???????????????????????? ?????????????? ??? ?????????????????????? ???????? ???? ????? 1?????????1?????????????????????2??????????????????????? 3????????????????? 2?????????1????????????????????????2?????????????????????? ???????????3???????????????????4??????????????????????? 3????????????1???????????????????????????2??????????????? ????3???????????????????????? ???? ??? 1????????????2?????????????????3????????1?????????????? 2???????????????????????3????????????????????????4???????? 1???????????????2??????????????????5??????????????6???????????? ?????????????? ???? ????? 1??????2???????????????????????3???????????8????????????? ???? B?????????????????????????? ????? ?????????????????????????????? ??????????????????????? 1.???????????????2.???????????? 3.?????????????????????????? ????????????????????????????? 4.???????????????? 5.???????? ???????? ??????????????????? 1.??????????2.??????????????????? 3.???????????????????? 4.??? ????????????????????? 5.??????????? 6.?????????????????????? ?????????????????????? 1.?????????????????? 2.????????????? 3.???????????????????? 4.??????????????????? 5.???????????? ???????????????????????????????? ??????????????????? 1????????????????????????????? ????----?XXX??????????????XXX??????100%???????XXX????????? 2?????????????????????????? ????----?XX??????????????XX???????? 3???????????????--?XX??XX????????? 4????????????---?XXX?????????????XXX??????? 5???????????????????????????----?XXX????????XXX?????????????????? ---------------------------------------------------------------------------------------------------------------------- ???? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ?????? ????????????????????????????/???????????????????????????????? ??????????????????????MBA?????MBA????????????????MBA????????????? ???????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????? --------------------------------------------------------------------------------------------------------------------- ?2009????????????????????? ??????????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From erg at vyue.com Sat Sep 19 21:50:13 2009 From: erg at vyue.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Sat, 19 Sep 2009 21:50:13 -0000 Subject: (no subject) Message-ID: <200909192150.n8JLnx4v018297@mx1.redhat.com> ????????????? ?????2009?9?26-27? ?? ? ??2200?/?????????????????? ??????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ----------------------------------------------------------------------------------------------- ??????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ?????????. ??????????????????????????????????????????????? ??????????????????????????????????????????????! ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????? ??????????????????????????????????? -------------------------------------------------------------------------------------------- ???????????? l?????????????????????????????????????????? 2??????????????????????????????? 3?????????????????????????????????????????? 4????????????????????????????????????????????? 5???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????? -------------------------------------------------------------------------------------------- ????? l??????????????????????????????? 2??????????????????? 3????????????????????? 4???????????????????????????? 5??????????????TPM???????? ????? l????????????????????????? 2???????????????????????????????????? 3???????????????????????????????????????????? -------------------------------------------------------------------------------------------- ????? ??????????????? ??????????? ????????????????? ????????????? ?????/?????/????? ?????????????? ??????????? ????????????? ????????????? ???????????????? ????????????????? ???????????????? ???????????????? ???????????? ???????????? ??????????????? ???????????? ??????????? ?????????????? ???????????????? ??????????????? ???????(?????) ?????????????? ????????? ??????????? ????????? ??????????? ????????????? ??:??????????? ???? ??N?????/??????? ???ISO9000??????????? ??????????????? ????????????????TPS? ???????????TOYOTA??? ????????????? ????5S??????????? ????5S????????????? ?5S????????????5??S? ???????5S?????6S?7S? ???????????? ???????????????? ????????????????? ???????????????????? ?????????????????? ????TQM?6?????????? ????????????????????????? ??????????????????? ??????????????? ???TPM??????????????????? ???TPM????????? ???: ???? ???? ??????????? ??????????? ?????????? ????????? ????????? ??: ??????????? ?????????????? ??????? ?????????????????? ??????????? ??????????????? ---???????????,??????????????) ---????????? ---????????? ---???????????? ??????/????????????; ???? 1.??????????????? 2.?????????? ?????????????????; ---???????????? ------------------------------------------------------------------------------------------------------------- ?????????? ?????? ???????? ???????????????(SUMIDA)????????(CASIO) ???13??????????????????????????????????????????????? ??WF&IE ???????????????????????????????????????????????????????JIT ??????NPS????????????? ??????????????(??,??,??,??,?????)????? ?:??????????ST?????????????????????????????????????????????? ???????????????????????????????80?????? ?????????????????????????????????????????????ABB?????????? ?????-??????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ?????????????????????????????? ??????????????????,?????????????????????????????????????? ?????????????????????????? ------------------------------------------------------------------------------------------------------------- ????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From gry3k.xxda at msn.com Tue Sep 22 22:05:47 2009 From: gry3k.xxda at msn.com (gry3k.xxda at msn.com) Date: Tue, 22 Sep 2009 22:05:47 -0000 Subject: (no subject) Message-ID: <200909222205.n8MM5YfC004413@mx1.redhat.com> ============================================================================== ?????-??????????? ============================================================================== ????? 2009?11?07-09??????? ?? 2009?11?14-16??????? ?? ?????????400-8899,628 ???????021-5109,9475 ???????020-3366,5697 / 3452,0981 ???hrlawclub @126. com ============================================================================== ?????? ??????30?????????????????/???????????? --?????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ?????????????? --??CEO????????????????????? ????????????? ?????????????????????????????? ????CEO??? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ???????????????? ?????????????????????????????? ?????????????????? ?????????????????? 2009???????????????? ?????? ????CEO???????????????????? ????? ?????????????3800? ?????5800?/?????????/????/??????/??? ============================================================================== ?????? ??????????????????????????? ???????? ??????????????????????????????????????? ???????? ??????????????????????????????????????? ?? ???????? ??????????????????????????????????????? ?? ============================================================================== ?????? ??????11?7? 9:00-17:00 ?????? ?????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ???????????????????????????????????????? -????????????????????????????? -?????????1-2??????????????????? -????????/??/?????????????????????? ??????????????????????????????????? ?????????????????????????????????? -????????/????????????????????????? ??????????????????????????????????? ??????????????????????-??-??-???????? -????????????????????????????????? ?????????????????????????????????? ?????????????????????????????????? ??????11?8? 9:00-17:00 ?????? ?????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ?????????? --??????????????????????????????/??/????? ??????????????????? --??????????-??????,????????????????????? ???????????????? ??????????????????????????????? -???????????????????????????? -??????????????????????????????? -???????????????????????????????? ??????????????????????????????? -????????????????????????????? -???????????????????????????????? -??????????????????????????????? ??????11?9? 9:00-12:00 ?????/14:00-17:00 ?????? ?????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????? -?????????????????????????????????????? ?;?????????????????????????; ????????????????????????????? -??????????????????? -?????????????????????????????? -????????????????????? -???????????????????? ???????????????????????????????? -??????????????????????????????? -??????????????????????????????? -??????????????????????????????? -??????????????????????????????? ============================================================================== ??????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ????????1990????????????????????????????? ????? ????????2001?-2003????????2003????????????? ?? ???????????????2005?????????????????????? ??????????????????????? ------------------------------------------------------------------------------ ??????? ??????????????????????????????????????? ??????15???????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ????????????? ??HPO?????????????????????? ???????? ??????????????????????????????????????? ??????????????????????????????????????? ?????????????? ------------------------------------------------------------------------------ ???????? ??????????????????????????????????????? ???????????? ------------------------------------------------------------------------------ ??????? ??????????????????????????????????????? 500??????. ============================================================================== ??????: ? ?? ???/??????????????????????????????????TOC ???????????????????????????? ???? ??????????????????????????????????????? ?????????????????????????? ???? ??????????????????????????????????????? ?????????????????????????????????? ---------------------------------------------------------------------------- 2009?11?7??? 18?00-19?25 ??????????????????????????? 19?35-21?00 ???????????????????????????? ---------------------------------------------------------------------------- 2009?11?8??? 18?00-19?25 ????????????????????????? 19?35-21?00 ????????????????????????????? ============================================================================== ????? MMC???? ???????????? ============================================================================== From jasrytowr at gmail.com Wed Sep 23 01:17:24 2009 From: jasrytowr at gmail.com (Angelina.Cheng) Date: Wed, 23 Sep 2009 01:17:24 -0000 Subject: (no subject) Message-ID: <200909230117.n8N1HC0J011545@mx1.redhat.com> ============================================================================================== ???????????????????????????????? ============================================================================================== ???????????? 2009??10??16-17?? ???? 2009??10??23-24?? ???? 2009??12??11-12?? ???? 2009??12??18-19?? ???? ??????????????????400-8899,628 ??????????????021-5109,9475 ??????????????020-3366,5697 / 3452,0981 ?? ????rdwork@ 126.com ============================================================================================== ??-??-??-??: ?????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????? ?????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ??????????????????????????????????????????30%??????????????70%?????????????????????????????????? ?????????????????????????????????????????????????????????????????? ??-??-??-???? ?????????????????????????? 1?????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????? 2????????????????????????KPI?????????????????????????????? 3???????????????????????????????????????????? 4?????????????????????????????????????? 5???????????????????????????????????????????????????????? 6?????????????????????????????????????? 7????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ?????????????????????????? ?????????????????????????????????????????????????????????????????? ???????????????????????????? ??KPI?????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????? ??-??-??-???? ????????????CEO/??????????????????????????/????????????/??????????????????/HR????????HR???????? /?????????????????????????????????????????????????? ??-??-??-???? ?? ?????? ?????? ?????? ?? ???????????????????????????????????????????????? ============================================================================================== ??-??-??-???? ???????????????????????????????????? 1.?????????????????????????????? 2.???????????????????? 3.?????????????????????????????????? 4.??????????????????????HR?????????????? 5.??????????????????????HR?????????????? 6.?????????????????????????????????? 7.?????????????????????????????? ?????????? ?????????????????????????????? 1. ?????????????????????????? 1?? ???????????????????????????????????????? 2?? ?????????????????????????????????? 3?? ?????????????????????????????????? 4?? ?????????????????????????????????????????????????????????? 5?? ???? 2. ?????????????????????????????????? 3. ???????????????? 4. ???????????????????? 1?? ???????????????? 2?? ???????????????????? 3?? ?????????????????? 5. ??????????????PDCA ???????????????????????????????????? 6. ?????????????????????????????????? 7. ???????????????????????????? 8. ???????????????????????????? 1?? ???????? 2?? ?????????? 3?? ?????????????????????????????????????????????? 9. ???????????????????????????? 1?? ???????????????????? 2?? ???????????????????????????????? 3?? ?????????????????? 10. ?????????? 1?? ???????????????????????????????? 2?? ???????????????????????????????????????????? 11. ?????????????? ?????????????????????????????????????? 1. ???????????????????????????????? 2. ???????????????????????????????????????? 3. ???????????????????????????? 1?? ???????????????? 2?? ?????????????????????????????????????????? 3?? ?????????????????? 4. ?????????????????????????? 5. ?????????????????????? 6. ?????????????????????? 1?? ???????????????????????? 2?? ??????????????????????????KPI?? 7. ?????????????????????? 1?? ?????????? 2?? ?????????????? 8. ???????????????????????????? 1?? ???????????? 2?? ?????????????????????????? 3?? ???????????????????? 9. ?????????? 1?? ???????????????????????????????????????????? 2?? ???????????????????????????????????? 10. ?????????????? ???????????????????????????????????? 1.?????????????????????????????????? 1???????????? 2???????????????? 3?????????? 4???????????? 5???????? 6???????????? 7???????????? 8???????????? 9???????????????? 10???????? 11???????????? 12???????? ?????????????????????????????? KPI ???????? 1.??KPI????????????IP??????K??IK???? 1????????????????KPI 2????????????????????KPI 3????????????????????KPI 4??????????????????????KPI 2.????????????????KPI?????????????? 3.????????????????????KPI?????????? ??????????????????????????KPI???????????? ????????????????????????KPI?????????? 4. ????????KPI ???????????????????? 5. ????????????????????????????????????KPI ???? 6. ????????KPI ?????????????? 7. ????????KPI ?????????? 1?? ???????????????? 2?? ???????????? 8. ????????KPI ??????????????????I??T??Q??C??S?? 9. ??????????KPI ?????? 1?? ????????KPI ???? ???????????????????????????????????????????? 2?? ????????KPI ????????????????????????????????????QA?????? 3?? ??????????????KPI ????????????HR?????????????????????????? 10. ????????KPI ?????? 11. ?????????????????? 1?? ???????????????????????????? 2?? ?????????????????????? 3?? ??????????????KPI ???????????? 4?? ?????????????????????????????????????????????? 12. ?????????? 1?? ????????????????????KPI ?????????????????????????????????????????????? 2?? ??????????KPI ?????????????????????????D?D??????????????PCB 13. ?????????????? ???????????????????????????? 1. ?????????????????????????? 2. ?????????????????????? 1?? ?????????????????? 2?? ?????????????????????????????????????????????????????? 3. ?????????????????? 1?? ???????? 2?? ???????? 3?? ?????????????? 4. ???????????????????????D?D????????????PBC 1?? ??????????WINNING?? 2?? ??????????EXECUTION?? 3?? ??????????TEAMWORK?? 5. ????????????????PBC ?????????????? 6. ????????????????????????????????PBC 7. ?????????????????????????????????? 1?? ???????????????????????? 2?? ???????????????????????????????????????????? 3?? ???????????????????????????????????????? 8. ??????????????????????????PIP?? 9. ?????????? 1?? ????????????????????????PBC ???????? 2?? ?????????????????????????????????????????????????????????????????????????????? 10. ?????????????? ????????????????????????/?????????????? 1. ???????????????????????? 1?? ????????????PAC 2?? ????????????PDT 3?? ????????FT 2. ???????????????????????? 3. ?????????????????????? 1?? ???????????????????????? 2?? ???????????? 3?? ???????????????? 4. ?????????????????????? 5. ?????????????????????????? 6. ?????????????????????????? 7. ?????????????????????????????????? 1?? ?????????? 2?? ?????????? 3?? ?????????? 4?? ?????????? 8. ?????????? 1?? ???????????????????????????????????????????? 9. ?????????????? ?????????? ???????????????????????????? 1. ??????????????????????????????????????????HR???????? 2. ?????????????????????????????????????????? 3. ???????????????????????????????????????????????????? 4. ???????????? 1?? ?????????????????????? 2?? ???????????????????????????????????????????????????????????? 3?? ???????????????????????????? 4?? ?????????????????????????????????? 5. ???????????????????????? 1?? ?????????????? 2?? ?????????????????????? 3?? ???????????????????????????????????????????????????????????????????? 6. ?????????????????????? 1?? ?????????????? 2?? ?????????????????????????? 7. ???????????????????????????????????????????????? 8. ???????????????????????? 9. ???????????????????????????????????????????? 1?? ???????? 2?? ???????? 3?? ???????????????? 10. ?????????? 1?? ???????????????????????????????????????? 11. ???????? ?????????? ???????????????????????????????????????????????????? 1.??????????????9?????????? 1?????????????????? 2?????????????????? 3?????????? 4?????????? 5?????????? 6?????????? 7??????????????????????????????????????????????????????????????BUG???????????????????????????? ???????????????? 8?????????????????? 9???????????????????????? 2. ?????????????????????? 3. ???????????????????????????????????????????? 4. ?????????????????????? 5. ?????????????? 1?? ??????/?????? 2?? ?????? 3?? ?????? 4?? ?????? 5?? ?????? 6. ?????????????????? 7. ?????????????????????????????????????? 8. ?????????????????????????????????????????? 9. ?????????? 1?? ?????????????????????????????????????????? 2?? ?????????????????????????????????????????????? 10. ???????? ============================================================================================== ?????? (????????????????????????????????????????????) ????????????????????: ==>????????????:????????????,?????????????????????? ==>????????:?????????????????????????????????????????????????????? ??????????: 10???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????IBM????????????????????????????????????????????I PD?????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????? ?????????????????????????? ==>????????????????????(????????????????) ==>??????????????????????????(??????????????????????????????????????) ==>???????????????????????????????????????????????????????????????????? ==>???????????????????????????????????? ??????????: ???????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ??????????: ?????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????10?????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ============================================================================================== ???????????????????? ------------------------------------------ M M C ?? ?? ?? ?? ??????????????????400-8899,628 ??????????????021-5109,9475 ??????????????020-3366,5697 / 3452,0981 ?? ????rdwork@ 126.com ??-??-??-??: ??????????-??-?? ?? ??????-???? ?? ?????????? ?? ???????????? ??====????2,500??/?? ???????????????????????????????????????????????? ============================================================================================== From xdr at drwx.com Thu Sep 24 04:23:44 2009 From: xdr at drwx.com (=?GB2312?B?x+vXqs/gudiyv8PF?=) Date: Thu, 24 Sep 2009 04:23:44 -0000 Subject: (no subject) Message-ID: <200909240423.n8O4NWlV028781@mx1.redhat.com> ?????????? ????? 2009?10?21?25? ?? ? ??9900?/????????????????????2??2??????9????9?30??????????9???? ?????40????????????? ?????1???????????????????????????????????????????????????? 2??????????????????????? 3??????????????????????? 4???????????????????????????????? 5?????????????????? ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------------------------- ???? 1?????????????????????????? 2?????????????????????????????????????VC/PE????????????????? ??????????? 3????????????????? -------------------------------------------------------------------------------------------------------------- ???? ??????????????????????????????????? ?????????????????????1980?/??? ?????????????????????????????????? --------------------------------------------------------------------------------------------------------------------- ??????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????? ?????????????????????????????????????? --------------------------------------------------------------------------------------------------------------------- ?????2009?3?31??????????????????????????????????????????? ????????????????????????????????????????????????????2007?9?? ??????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????? ---------------------------------------------------------------------------------------------------------------------- ????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????? ?????????????????????? ????????????????????????????????????????? --------------------------------------------------------------------------------------------------------------------- ???????????????????????????????????????????????????????????? ???????????????? ????????? ???????????????????? ???? ????????? ???? ????? ?????????????? ????????? ????????? ???????????? ??????? ?????????? ???????????????? ????????????? ??????? ?????????????? ??????? ????????? ???????? ???? ???????????? ???? ????????? ?????????????? ??????? ???? ??????? ???? ????????? ????????????? ???????????? ????????? ????????? ?????? ????????????? ??????? ??????? ????????????? ????????????????????????????????????????????? ------------------------------------------------------------------------------------------ ?????????????????????020-62351156? ???????_______________________________________________________ ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From vghyuiol98 at yahoo.com Thu Sep 24 23:52:58 2009 From: vghyuiol98 at yahoo.com (Abby.Ai) Date: Thu, 24 Sep 2009 23:52:58 -0000 Subject: (no subject) Message-ID: <200909242352.n8ONqk6B026934@mx1.redhat.com> ============================================================================================== ???????????????????????????????? ============================================================================================== ???????????? 2009??10??16-17?? ???? 2009??10??23-24?? ???? 2009??12??11-12?? ???? 2009??12??18-19?? ???? ??????????????????400-8899,628 ??????????????021-5109,9475 ??????????????020-3366,5697 / 3452,0981 ?? ????rdwork@ 126.com ============================================================================================== ??-??-??-??: ?????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????? ?????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ??????????????????????????????????????????30%??????????????70%?????????????????????????????????? ?????????????????????????????????????????????????????????????????? ??-??-??-???? ?????????????????????????? 1?????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????? 2????????????????????????KPI?????????????????????????????? 3???????????????????????????????????????????? 4?????????????????????????????????????? 5???????????????????????????????????????????????????????? 6?????????????????????????????????????? 7????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ?????????????????????????? ?????????????????????????????????????????????????????????????????? ???????????????????????????? ??KPI?????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????? ??-??-??-???? ????????????CEO/??????????????????????????/????????????/??????????????????/HR????????HR???????? /?????????????????????????????????????????????????? ??-??-??-???? ?? ?????? ?????? ?????? ?? ???????????????????????????????????????????????? ============================================================================================== ??-??-??-???? ???????????????????????????????????? 1.?????????????????????????????? 2.???????????????????? 3.?????????????????????????????????? 4.??????????????????????HR?????????????? 5.??????????????????????HR?????????????? 6.?????????????????????????????????? 7.?????????????????????????????? ?????????? ?????????????????????????????? 1. ?????????????????????????? 1?? ???????????????????????????????????????? 2?? ?????????????????????????????????? 3?? ?????????????????????????????????? 4?? ?????????????????????????????????????????????????????????? 5?? ???? 2. ?????????????????????????????????? 3. ???????????????? 4. ???????????????????? 1?? ???????????????? 2?? ???????????????????? 3?? ?????????????????? 5. ??????????????PDCA ???????????????????????????????????? 6. ?????????????????????????????????? 7. ???????????????????????????? 8. ???????????????????????????? 1?? ???????? 2?? ?????????? 3?? ?????????????????????????????????????????????? 9. ???????????????????????????? 1?? ???????????????????? 2?? ???????????????????????????????? 3?? ?????????????????? 10. ?????????? 1?? ???????????????????????????????? 2?? ???????????????????????????????????????????? 11. ?????????????? ?????????????????????????????????????? 1. ???????????????????????????????? 2. ???????????????????????????????????????? 3. ???????????????????????????? 1?? ???????????????? 2?? ?????????????????????????????????????????? 3?? ?????????????????? 4. ?????????????????????????? 5. ?????????????????????? 6. ?????????????????????? 1?? ???????????????????????? 2?? ??????????????????????????KPI?? 7. ?????????????????????? 1?? ?????????? 2?? ?????????????? 8. ???????????????????????????? 1?? ???????????? 2?? ?????????????????????????? 3?? ???????????????????? 9. ?????????? 1?? ???????????????????????????????????????????? 2?? ???????????????????????????????????? 10. ?????????????? ???????????????????????????????????? 1.?????????????????????????????????? 1???????????? 2???????????????? 3?????????? 4???????????? 5???????? 6???????????? 7???????????? 8???????????? 9???????????????? 10???????? 11???????????? 12???????? ?????????????????????????????? KPI ???????? 1.??KPI????????????IP??????K??IK???? 1????????????????KPI 2????????????????????KPI 3????????????????????KPI 4??????????????????????KPI 2.????????????????KPI?????????????? 3.????????????????????KPI?????????? ??????????????????????????KPI???????????? ????????????????????????KPI?????????? 4. ????????KPI ???????????????????? 5. ????????????????????????????????????KPI ???? 6. ????????KPI ?????????????? 7. ????????KPI ?????????? 1?? ???????????????? 2?? ???????????? 8. ????????KPI ??????????????????I??T??Q??C??S?? 9. ??????????KPI ?????? 1?? ????????KPI ???? ???????????????????????????????????????????? 2?? ????????KPI ????????????????????????????????????QA?????? 3?? ??????????????KPI ????????????HR?????????????????????????? 10. ????????KPI ?????? 11. ?????????????????? 1?? ???????????????????????????? 2?? ?????????????????????? 3?? ??????????????KPI ???????????? 4?? ?????????????????????????????????????????????? 12. ?????????? 1?? ????????????????????KPI ?????????????????????????????????????????????? 2?? ??????????KPI ?????????????????????????D?D??????????????PCB 13. ?????????????? ???????????????????????????? 1. ?????????????????????????? 2. ?????????????????????? 1?? ?????????????????? 2?? ?????????????????????????????????????????????????????? 3. ?????????????????? 1?? ???????? 2?? ???????? 3?? ?????????????? 4. ???????????????????????D?D????????????PBC 1?? ??????????WINNING?? 2?? ??????????EXECUTION?? 3?? ??????????TEAMWORK?? 5. ????????????????PBC ?????????????? 6. ????????????????????????????????PBC 7. ?????????????????????????????????? 1?? ???????????????????????? 2?? ???????????????????????????????????????????? 3?? ???????????????????????????????????????? 8. ??????????????????????????PIP?? 9. ?????????? 1?? ????????????????????????PBC ???????? 2?? ?????????????????????????????????????????????????????????????????????????????? 10. ?????????????? ????????????????????????/?????????????? 1. ???????????????????????? 1?? ????????????PAC 2?? ????????????PDT 3?? ????????FT 2. ???????????????????????? 3. ?????????????????????? 1?? ???????????????????????? 2?? ???????????? 3?? ???????????????? 4. ?????????????????????? 5. ?????????????????????????? 6. ?????????????????????????? 7. ?????????????????????????????????? 1?? ?????????? 2?? ?????????? 3?? ?????????? 4?? ?????????? 8. ?????????? 1?? ???????????????????????????????????????????? 9. ?????????????? ?????????? ???????????????????????????? 1. ??????????????????????????????????????????HR???????? 2. ?????????????????????????????????????????? 3. ???????????????????????????????????????????????????? 4. ???????????? 1?? ?????????????????????? 2?? ???????????????????????????????????????????????????????????? 3?? ???????????????????????????? 4?? ?????????????????????????????????? 5. ???????????????????????? 1?? ?????????????? 2?? ?????????????????????? 3?? ???????????????????????????????????????????????????????????????????? 6. ?????????????????????? 1?? ?????????????? 2?? ?????????????????????????? 7. ???????????????????????????????????????????????? 8. ???????????????????????? 9. ???????????????????????????????????????????? 1?? ???????? 2?? ???????? 3?? ???????????????? 10. ?????????? 1?? ???????????????????????????????????????? 11. ???????? ?????????? ???????????????????????????????????????????????????? 1.??????????????9?????????? 1?????????????????? 2?????????????????? 3?????????? 4?????????? 5?????????? 6?????????? 7??????????????????????????????????????????????????????????????BUG???????????????????????????? ???????????????? 8?????????????????? 9???????????????????????? 2. ?????????????????????? 3. ???????????????????????????????????????????? 4. ?????????????????????? 5. ?????????????? 1?? ??????/?????? 2?? ?????? 3?? ?????? 4?? ?????? 5?? ?????? 6. ?????????????????? 7. ?????????????????????????????????????? 8. ?????????????????????????????????????????? 9. ?????????? 1?? ?????????????????????????????????????????? 2?? ?????????????????????????????????????????????? 10. ???????? ============================================================================================== ?????? (????????????????????????????????????????????) ????????????????????: ==>????????????:????????????,?????????????????????? ==>????????:?????????????????????????????????????????????????????? ??????????: 10???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????IBM????????????????????????????????????????????I PD?????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????? ?????????????????????????? ==>????????????????????(????????????????) ==>??????????????????????????(??????????????????????????????????????) ==>???????????????????????????????????????????????????????????????????? ==>???????????????????????????????????? ??????????: ???????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ??????????: ?????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????10?????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ============================================================================================== ???????????????????? ------------------------------------------ M M C ?? ?? ?? ?? ??????????????????400-8899,628 ??????????????021-5109,9475 ??????????????020-3366,5697 / 3452,0981 ?? ????rdwork@ 126.com ??-??-??-??: ??????????-??-?? ?? ??????-???? ?? ?????????? ?? ???????????? ??====????2,500??/?? ???????????????????????????????????????????????? ============================================================================================== From wefg at ereh.com Fri Sep 25 21:11:00 2009 From: wefg at ereh.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Fri, 25 Sep 2009 21:11:00 -0000 Subject: (no subject) Message-ID: <200909252110.n8PLAYoi010279@mx1.redhat.com> ???????????????????????????????? ??????????2009??10??16-17??---???? ??????????2009??10??23-24??---?? ?? ??????????????????????CEO/??????????????????????????????????????????/?????? ??????/??????????????????/HR????????HR????????/???????????????????????????? ?????????????????????????????????????????????????????????? ??====????2500??/2??/??(??????????????????????????????????????????????) ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ??????500?????????????????????????????????????????????? ============================================================================ ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ????????????????????????????????KPI???????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ???????????????????? ??????????????????????????????????????????30%??????????????70%???????????????? ?????????????????????????????????????????????????????????????????????????????????? ====================================================================================== ?????????????????????????? 1. ???????????????????????????????????????????????????????????????????????????????????? 2. ?????????????????????????????????????????????????????????????????? 3. ???????????????????????????????????????????????????????????????? 4. ?????????????????????????????????????????????????? 5. ??????????????????????????????????????KPI ???????????????????????????? 6. ????????????????????????????????????????PBC?? 7. ?????????????????????????????????????????????????????? 8. ??????????????PDCA ???????????????????????????? 9. ?????????????????????????????????????????????????????????????????????????????????? 10.????????20 ???????????????????????????????????????????????????????????????????? ??Action Plan??????????????????????????????????????????. ====================================================================================== ???????? ???????????????????????? 1???????????????????????? 1???????????????? 2???????????????? 3???????????????? 4?????????????? 5?????? 2???????????????????????????????? 3?????????????????????????????????????????????????? 4????????????A?????????? ???????????????????????????????????? 1?????????????????????????????? 1???????????????????????? 2??18???????????? 3?????????????????????????????? ???????????? ??B??E??I?????? 4?????????????????????????????????????????????????? 5???????????????????????????????? ?????????? ?????????? ???????????? ?????????????? ???????????????? ?????? 2?????????????????????????????????? 1???????????????????? ?????????? ?????????? ?????????????? 2?????????????????????????? 3???????????????????????????????????????? 4???????????????????????????????????????????????? ???????????????????????????? 1?????????????????????????????????? 2?????????????????????????????????????????? 3?????????????????????????????? 1?????????????????? 2???????????????????????????????????????????? 3???????????????????? 4???????????????????????????? 5???????????????????????? 6???????????????????????? 1?????????????????????????? 2??????????????????????????????????????????KPI?? 7???????????????????????? 1???????????? 2???????????????? 8?????????????????????????????? 1?????????????? 2???????????????????????????? 3?????????????????????? 9???????????? 1?????????????????????????????????????????????? ????????????????????KPI ???????? 1??????????KPI ???????????????????? 2??????????????????????????????????????KPI ???? 3??????????KPI ?????????????? 4??????????KPI ?????????? 1?????????????????? 2?????????????? 5??????????KPI ??????????????????I??T??Q??C??S?? 6????????????KPI ?????? 1??????????KPI ???? ???????????????????????????????????????????? 2??????????KPI ????????????????????????????????????QA?????? 3????????????????KPI ????????????HR?????????????????????????? 7??????????KPI ?????? 8???????????????????? 1?????????????????????????????? 2???????????????????????? 3????????????????KPI ???????????? 4???????????????????????????????????????????????? 9???????????? 1??????????????????????KPI ?????????????????????????????????????????????? 2????????????KPI ???????????????????????D?D??????????????PCB ?????????????????????? 1???????????????????????????? 2???????????????????????? 1???????????????????? 2???????????????????????????????????????????????????????? 3???????????????????? 1???????????????????? 2?????????? 3???????????????? 4?????????????????????????D?D????????????PBC 1????????????WINNING?? 2????????????EXECUTION?? 3????????????TEAMWORK?? 5??????????????????PBC ?????????????? 6??????????????????????????????????PBC 7???????????????????????????????? 8????????????????????????????PIP?? 9???????????? 1??????????????????????????PBC???????? 2??????????????????????????PIP???????? ????????????/?????????????? 1?????????????????????????? 1??????????????PAC 2??????????????PDT 3??????????FT 2?????????????????????????? 3???????????????????????? 1?????????????????????????? 2?????????????? 3?????????????????? 4???????????????????????? 5???????????????????????????? 6???????????????????????????? 7?????????????????????????????????????????????? 1???????????? 2???????????? 3???????????? 4???????????? 8???????????? 1?????????????????????????????????????????????? ???????????????????????????? 1????????????????????A??????????????B?????????????????????????????????????????????? 1???????????????????????????????????????????? 2?????????????????????????????????????????? 2????????????????????????????????????????????HR???????? 3???????????????????????????????????????????? 4?????????????????????????????????????????????????????? 5?????????????? 1???????????????????????? 2?????????????????????????????????????????????????????????????? 3?????????????????????????????? 4???????????????????????????????????? 6?????????????????????????? 1???????????????? 2?????????????????????????????????????????????????????????????????????? 7???????????????????????? 1???????????????? 2???????????????????????????? 8?????????????????????????????????????????????????? 9?????????????????????????????????????????????? 1?????????? 2?????????? 3?????????????????? 10?????????????????????????????????????????? 11???????????? 1?????????????????????????????????????????? ???????????????????????????? 1?????????????????????????? 2???????????????????? 1???????? 2??5??/10???????? 3???????? 4???????? 5?????? 6?????? 2?????????????????????????????????????????????? 3???????????????? 1????????/?????? 2???????? 3???????? 4???????? 5???????? 4???????????????????????????????????????? 5?????????????????????????????????????????????????????? ====================================================================================== ???????????????????? ???????????????????????????????????????????????? ?????????????????????? ==>?????????????????????? ???????? & ?????????? ==>???????????????????????????????????????????????? ???????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????????????????? ==>???????????????????? ==>?????????????????????????? ==>?????????????????????????? ==>???????????????????????????????????????? ???????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ???????????????????????????????? ??????????????????????????????????????????????????????(????)?????? ??????????????????????????????????????????????????????????????????????????????????(????)???????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From eru at tyx.com Fri Sep 25 22:11:45 2009 From: eru at tyx.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Fri, 25 Sep 2009 22:11:45 -0000 Subject: (no subject) Message-ID: <200909252211.n8PMBUxd024304@mx1.redhat.com> ??EHS?????????????????????????????????? ??????????2009??10??17-18?? ?? ?? ??????????2009??10??24-25?? ?? ?? ??????????????????/????????????????????/??????????/????????????????????????????????;???????????? ?????????????????????????????????? ?? ????2000??/??(??????????????????????????????????????????????) ??????????500?????????????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ====================================================================================== ?????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????GDP??????1/5???? 13?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????? = 45???????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????? ???????????????????????????? ???????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ====================================================================================== ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????.?????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ??????????????, ?????????????????????????????????????????????????? ========================================================================================== ???????? ????EHS???????????????? 1??????EHS???? ??1??EHS?????????????????????????? ??2????????????EHS?????????? ??3??????????500?????????????????? 2??EHS?????????????????? ??1?????????????????????? ??2???????????????????? ??3???????????????????????????????? ??4?????????????????????? 3??????EHS?????????????????????? ??1?????????????????????? ??2?????????????????????? 4??EHS???????????????? ??1???????????????????????????????? ??2???????????????????????????? 5??EHS?????????????????????????? ??1???????? ???????????????????????????????????????????????????????? ??2???????????????? ??????????????????????????????????????SOP ??3?????????????????? ???????????????????????????????????????????????????????????????? ??4???????????? ???????????????????????????????????????????????????????????? 6?????????????????????????? ??1???????????????????????????????????????? ??2?????????? ?????????? PK ???? ????????????????????????EHS 1?????????????????????? ??1???????????????????????????????? ??2???????????????????????? ??3???????????????????? 2??EHS???????? ??1???????????? ??2???????????? ??3?????????????????? ??4??EHS?????????????????? ??5??EHS?????????????????????????? 3???????????????????? ???????????????????????????????????????????????????????????????? 4???????????????????? ???????????????????????????? PK ?????????????????????????????? 5?????????????????? ???????????????????????????????? 6?????????????????????? 7?????????????????????? PDCA??SDCA????????????????????ERP??8S??6SIGMA??IE 8???????????????????? ISO14000??OHSMS??SA8000??OHSA18000?????????????????????????????????? ???????????????????????? ??????????E?????????? 1??5S????????????EHS???? ???????????????????????? 2???????????????????????? ???????????????????????????????????????????????????? 3?????????? ???????????????????????????????????? 4?????????????? ?????????????????????????????????????? 5?????????? ?????????????????????? 6?????????????????????????? ?????????????????????????????????????????? ??????????H?????????? 1???????????????? 2???????????????????????? 3?????????? ???????????????????????? 4???????????????????? 5???????????????? ??????????S?????????? 1?????????????? 2???????????????????????? ???????????????????????????????????????? 3???????????????????????? ?????????????????????????????????????????? 4?????????????????????????? 5?????????????????????????? 6?????????????????? ?????????????????? ????EHS???????? 1?????????????????? 2???????????????????????? ?????????????????????????????? 3?????????????? ???????????????????????????????????????????????? 4???????????????? MSDS?????????????????? 5?????????????????? ???????????????????????????????????????? 6?????????????? ?????????????????????? 7?????????????????? ?????????????????????????????? 8?????????????? ?????????????????? ???????????????????????????? 1?????????????????????????? ???????????????????????????????????????????????? 2???????????????????? 3?????????????????????????? 4??????????????MFT??MRB 5???????????????????????????????????? 6?????????????????????????????????????????? ?????????????????????????? ????EHS?????????? 1?????????????????? 2?????????????????????????? 3???????????? ????????????????????Q&A) ====================================================================================== ????????:??????--?????????????????????????????????????????????????????????????????????????????????? ?????????????????? ????????????????????MBA???????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????SHE????????????????????????????(DWO)???????????????? ????????????????????SPC?? DOE??MSA??FMEA?? TQM??QFD????????,?????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????2000-2004??????????????????????/????/?????????????????????????? ??????: ????????????????????????????????????????????ISO9001??2000???????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????????????.?????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????600??????????????4000???????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????? ------------------------------------------------------------------------------- ????EHS??????????????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From lhjn.wdvb at msn.com Sat Sep 26 14:03:45 2009 From: lhjn.wdvb at msn.com (lhjn.wdvb at msn.com) Date: Sat, 26 Sep 2009 14:03:45 -0000 Subject: (no subject) Message-ID: <200909261403.n8QE3Y6L011717@mx1.redhat.com> ================================================================================ ????????????????????? ?????????????????????? ================================================================================ ?.?.?.?.?? 2009?10?17-18? ? ? 2009?10?24-25? ? ? ?.?.?.?.?.?.?.????????????? ?.?.?.?.?.?????????????? ?.?.?.?.?.?????????????? ?.??hrlawclub@ 126.com ================================================================================ ?.?.?.?: ?????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????? ?????????????????????????????????????? ????????????????????????????????? ?????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????? ?.?.?.?? --???????????????????????? --?????????????????????1000???????????????? ???????????????????????????????????????? ??????? --?????????????? ?.?.?.?? ???????????????????????????????????/???? ?.?.?.???????????????? ================================================================================ ?-?-?-? : ?????????????????????????????? ????????????????????? 1????????????????????????????????????......) 2????????????????????????????????? 3????????????????????? 4???????????????????? 5????????????????????????????????? 6???????????????????????????????????????? ???????? 7???????????????????????????????????????? ?????????????????? 8??????????????????????????? 9????????????????????????? ??????????????????????????????? 1???????????????????????? 2????????????????????????? 3???????????????????????????????????????? ??????????????????????????????08?1?1????? 4???????????????????????????????????????? ??????????????????????????????????????? ???????????? 5?????????????????????????? 6???????????????????????????????????????? ????????? 7??????????????????? 8??????????????????????????? 9??????????????????? 10??????????????????????????????????????? ???????? ????????????????? 1?????????? 2?????????????????????? 3??????????? 4???????????????? 5????????????????????? 6??????????????????? 7????????? ???????????????????????? ?????????????????????????????????? ??????????????? 1???????????????????????????? 2?????????????????????????????????????? 3?????????????????????????????? 4????????????????????????????????? 5????????????????????? 6????????????? 7?????????????????????? 8??????????????????????????????????? 9?????????????????? 10?????????????????? 11????????? 12????????? 13???????????????????????? 14????????????????????? ?????????????????? 1? ???????? 2? ????????? 3? ??????????????? 4? ???????????????? 5? ?????????? 6? ?????????? 7? ????????????? 8? ??????????????????? 9? ???????? 10?????????????????????????? ???????????????????????? ================================================================================ ????? ??? -?????????????? -????????????????????? ?????????????????????????????????????? ????????????2007?????????????????????????? ??95%?????????????????????? ?????????????? ??????????????????????? 07???????????300??? ?????1500??????????95%????????????1300??? ???? ????????? ?????????????????????????????????????? ???????????????????????????????????????? ??1000???????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ?????????????? ?????????????: ??????????SONY???????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ????HP??????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ?????(??)???????????????????????????????? ??????????????????????????????????????YKK ?????? ================================================================================ ???????????/??????????????????? ?.?.?.?.?.?.?.?.?? ------------------------------------------ M.M.C.? ? ? ? ?.?.?.?.?.?.?.????????????? ?.?.?.?.?.?????????????? ?.?.?.?.?.?????????????? ?.??hrlawclub@ 126.com ================================================================================ From wqsv at asef.com Sun Sep 27 19:44:52 2009 From: wqsv at asef.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Sun, 27 Sep 2009 19:44:52 -0000 Subject: (no subject) Message-ID: <200909271944.n8RJidJE025631@mx1.redhat.com> ??????????????????????PPT+Excel+?????????????????? ?????????????????????? ??????????????????????????????office2003??Office2007?? ??????????2009??10??30????11??1?????? ??????????2009??11??6-8?????? ??????????2009??11??20-22?????? ??????????3600/???????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc21 at 126.com?????? ====================================================================================== ??????????????20???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????3?????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????? ????????????????????????????Powerpoint??Excel???????????????????????????????????????????????????????? ???????????????????????????????????????????? Powerpoint??????????????????????????????????????????Powerpoint????????????????Office???????????????? ????????Powerpoint????????????????PPT?????????????????????????????????????????? ??????????Powerpoint???????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????Photoshp???????????? ?????????????????????????????????????????????????? Excel??????????????????????????????????????????????????????????????Excel??80%???????????????????????? ??????????????????????????????????????????5?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ============================================================================================== ????????????????????????????????????????????????????????????office2003??Office2007 ????PPT??????????????????????????????Powerpoint???????????????????????? 1.???????????????????????????????????????????????????????????? 2.?????????????????????????????????????????????????????????? 3.?????????????????????????????????????????????????????????????????????????????????????????????????????????? 4.Flash??????????????????????Flash??????????PPT??????????????????????Flash?? ?????????????????????????????????????????? ????Excel??????????????????????????????BladeOfficeExcel???????????????????????? 1.????????????????????????????????????????????????????????????????????Excel???????????????????????????? ???????????????????????????????????????????????????????? 2.Excel??????????????Excel2003???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ======================================================================================================== ???????? ???????????????????????? ?????????????????????????? 1.?????????????????????????????????????????????????????????? 2.????????????????????????500???????????????????????????????? 3.???????????????????????????????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????? ?????????????????????????? 1.????Office???????????????? 2.???????????????????? 3.?????????????????? 4.???????????????? 5.???????????????????????????????? 6.?????????????????? 7.????3D?????????????? 8.???????????????????????? 9.?????????????????? 10.??????????????* 11.??????????????????????????????????3-D????* ???????????????????????? 1.???????????? 2.???????????????????????? ???????????????????????? 3.???????????? ???????????????????????????????????? 4.????????????????40M??????????6M 5.???????????????? ????SmartArt???????? 1.?????????????????????????????? 2.???????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????????????? 6.??????????????SmartArt ???????????????????? 1.?????????????????????????????? 2.?????????????????????????? 3.?????????????????????????? 4.?????????????? 5.?????????????????????? 6.?????????????????? ????Excel???????? 1.?????????????????????????????????????????????? 2.??????????????????????????????10??????????5???????? 3.?????????????????????? 4.?????????????????? 5.???????????????????????????????????????????????? 6.??????Powerpoint???????????????????? 7.?????????????????????? 8.???????????????????????????????? 9.???????????????????????????????????? ?????????????????? 1.????????????Powerpoint?????????? 2.???????????????????????????? 3.?????????????????? 4.?????????????????????? 5.?????????????????????????????????? ???????????????????? 1.Powerpoint?????????????????? 2.?????????????????????????????????? 3.???????????????? 4.???????????????????????????????? 5.?????????????????????? 6.???????????????????????????????? 7.?????????????????????? 8.?????????????????????????????????????? ????????Excel?????????????? ???????????? 1.?????????????????? 2.?????????????????? 3.??????????2?????? 4.??????????????????Excel?????????????????????????????? 5.?????????????????????????????????? ???????????????? 1.????IF???????????????? 2.AND??OR??NOT???? 3.?????????????????????? ?????????????? 1.?????????????????? 2.???????????????????????????? 3.???????? a)???????????????????????????????? b)?????????? c)???????????????????? ???????????? 1.???????????? 2.???????????????????????? ???????????? 1.???????????????? 2.????VLOOKUP??HLOOKUP???????????? 3.?????????????????????? a)???????????????????????????????????? b)???????????????????????????????????????????????????????????????? 4.?????????????????????????? 5.???????????????????????????? ???????????? 1.???????????????? 2.?????????????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????? 6.?????????????????? ???????????? 1.?????????? 2.?????????? 3.???????????????? ???????????????? 1.???????????????? 2.???????????????? 3.?????????????????? 4.???????????????? 5.?????????????????????????? ?????????????????????? 1.?????????????? 2.?????????????? 3.???????????? 4.???????????? 5.???????????? 6.?????????????????????????????? 7.???????????????????? a)?????????? b)?????????? c)?????? d)?????????? 8.???????????????????????? 9.?????????????????????????????? ?????????????????? 1.?????????????????????? 2.???????????????????????????????? 3.?????????????????? ???????????????????? ?????????????????? 1.?????????????????? 2.????Powerpoint?????????????????? 3.????Word?????????????????? 4.????Excel?????????????????? ???????????? 1.?????????????????????????????????????????????? 2.???????????????? 3.??????????????SmartArt???????????? 4.???????????????????? ???????????????? 1.?????????????????? 2.???????????????????????????????? 3.Outlook?????????????????? ================================================================================================== ??????????????????????????????????????????????IPMP???????????????????????????????????????????????? ????????????????????????????????????????????????????????????????ERP???????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ??????????DELL????????????????????????????????????????????????????????????????????TCL???????? ============================================================================================== ????????????????????????PPT+Excel+??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????!