public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Oleg Nesterov <oleg@redhat.com>
To: Andrew Morton <akpm@linux-foundation.org>,
	Andy Lutomirski <luto@kernel.org>,
	Linus Torvalds <torvalds@linux-foundation.org>
Cc: Denys Vlasenko <dvlasenk@redhat.com>,
	"H. Peter Anvin" <hpa@zytor.com>, Ingo Molnar <mingo@redhat.com>,
	Jan Kratochvil <jan.kratochvil@redhat.com>,
	Pedro Alves <palves@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	x86@kernel.org, linux-kernel@vger.kernel.org
Subject: syscall_get_error() && TS_ checks
Date: Wed, 29 Mar 2017 18:33:35 +0200	[thread overview]
Message-ID: <20170329163335.GA23977@redhat.com> (raw)
In-Reply-To: <20170328145413.GA3164@redhat.com>

I must have missed something, but I simply can't undestand it.

	static inline long syscall_get_error(struct task_struct *task,
					     struct pt_regs *regs)
	{
		unsigned long error = regs->ax;
	#ifdef CONFIG_IA32_EMULATION
		/*
		 * TS_COMPAT is set for 32-bit syscall entries and then
		 * remains set until we return to user mode.
		 */
		if (task->thread.status & (TS_COMPAT|TS_I386_REGS_POKED))
			/*
			 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
			 * and will match correctly in comparisons.
			 */
			error = (long) (int) error;
	#endif
		return IS_ERR_VALUE(error) ? error : 0;
	}

Firstly, why do we need the IS_ERR_VALUE() check? This is only used by
do_signal/handle_signal, we do not care if it returns non-zero as long
as the value can't be confused with -ERESTART.* codes.

And why do we need the TS_ checks? IIUC only because a 32-bit debugger
can change regs->ax, and we also assume that if this happens outside of
syscall-exit path (so that TS_COMPAT is not set) then it should also
change regs->orig_ax and this implies TS_I386_REGS_POKED.

Oherwise it is not needed, even the 32-bit syscalls return long, not int.

So why we can't simply change putreg32() to always sign-extend regs->ax
regs->orig_ax and just do

	static inline long syscall_get_error(struct task_struct *task,
					     struct pt_regs *regs)
	{
		return regs-ax;
	}

? Or, better, simply kill it and use syscall_get_return_value() in
arch/x86/kernel/signal.c.

Of course, if the tracee is 64-bit and debugger is 32-bit then the
unconditional sign-extend can be wrong, but do we really care about
this case? This can't really work anyway. And the current code is not
right too. Say, debugger nacks the signal which interrupted syscall
and sets regs->ax = -ERESTARTSYS to force the restart, this won't work
because TS_COMPAT|TS_I386_REGS_POKED are not set.

Oleg.

  parent reply	other threads:[~2017-03-29 16:33 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-28 14:54 [PATCH 0/1] get_nr_restart_syscall() should return __NR_ia32_restart_syscall if __USER32_CS Oleg Nesterov
2017-03-28 14:54 ` [PATCH 1/1] " Oleg Nesterov
2017-03-28 15:03   ` Andy Lutomirski
2017-03-28 16:27     ` Oleg Nesterov
2017-03-28 17:10       ` Andy Lutomirski
2017-03-29 15:05       ` Oleg Nesterov
2017-03-29 16:59         ` Andy Lutomirski
2017-03-30 15:28           ` Oleg Nesterov
2017-03-30 18:36             ` Andy Lutomirski
2017-03-29 16:33 ` Oleg Nesterov [this message]
2017-03-29 16:45   ` syscall_get_error() && TS_ checks Linus Torvalds
2017-03-29 16:55     ` Oleg Nesterov
2017-03-29 16:59       ` Linus Torvalds
2017-03-29 17:04         ` Oleg Nesterov
2017-03-29 17:16           ` Linus Torvalds
2017-03-29 18:50             ` Oleg Nesterov
2017-03-29 18:56               ` Linus Torvalds
2017-03-30 13:51                 ` Oleg Nesterov
2017-03-30 15:49                   ` Oleg Nesterov
2017-03-30 17:46                     ` Linus Torvalds
2017-03-30 18:23                       ` Andy Lutomirski
2017-03-30 18:35                         ` Linus Torvalds
2017-03-30 18:59                           ` Andy Lutomirski
2017-03-30 19:11                             ` Linus Torvalds
2017-03-30 19:21                               ` Andy Lutomirski
2017-03-30 19:29                                 ` Linus Torvalds
2017-03-29 16:56     ` Andy Lutomirski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170329163335.GA23977@redhat.com \
    --to=oleg@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=dvlasenk@redhat.com \
    --cc=hpa@zytor.com \
    --cc=jan.kratochvil@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mingo@redhat.com \
    --cc=palves@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox