From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf0-f181.google.com ([209.85.192.181]:36567 "EHLO mail-pf0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754816AbdCTRff (ORCPT ); Mon, 20 Mar 2017 13:35:35 -0400 Received: by mail-pf0-f181.google.com with SMTP id o126so68799145pfb.3 for ; Mon, 20 Mar 2017 10:35:34 -0700 (PDT) Received: from gmail.com ([2620:0:1008:13:6000:704c:d727:b18d]) by smtp.gmail.com with ESMTPSA id q4sm16333083pgc.63.2017.03.20.10.35.33 for (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 20 Mar 2017 10:35:33 -0700 (PDT) Date: Mon, 20 Mar 2017 10:35:31 -0700 From: Eric Biggers To: linux-fsdevel@vger.kernel.org Subject: Data in source pipe can be modified after sys_tee()? Message-ID: <20170320173531.GB26906@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Sender: linux-fsdevel-owner@vger.kernel.org List-ID: Hello, I noticed a strange behavior involving the tee() system call. Here's a sample program: #define _GNU_SOURCE #include #include #include #include #include int main() { int pipe_A[2]; int pipe_B[2]; char buffer[2] = { 0 }; pipe(pipe_A); pipe(pipe_B); write(pipe_A[1], "AA", 2); tee(pipe_A[0], pipe_B[1], 1, 0); write(pipe_B[1], "B", 1); read(pipe_A[0], buffer, 2); printf("%.*s\n", 2, buffer); assert(!memcmp(buffer, "AA", 2)); return 0; } It creates two pipes A and B, then writes two bytes "AA" to pipe A, then tee()s one byte from pipe A to pipe B, then writes one byte "B" to pipe B. At that point, I expected pipe A to still contain the bytes "AA", because tee() does not consume the source data, nor was any data written to pipe A; nor should it be possible to modify data already in a pipe (unless it was put there by splice() or vmsplice()). However, the actual behavior is that pipe A contains the bytes "AB". This happens because the second byte was overwritten by the write to pipe B, as the data in both pipes are backed by the same page, and the pipe is using anon_pipe_buf_ops which has .can_merge = 1, so the backing page can be written to by pipe_write(). Is this a bug? It certainly seems like it; you should *not* be able to modify data in a pipe, given only the read end. - Eric