From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.5 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_PASS,USER_AGENT_MUTT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 946AEC282C2 for ; Sun, 10 Feb 2019 04:24:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6302520873 for ; Sun, 10 Feb 2019 04:24:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726834AbfBJEYn (ORCPT ); Sat, 9 Feb 2019 23:24:43 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:53750 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726699AbfBJEYm (ORCPT ); Sat, 9 Feb 2019 23:24:42 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.91 #2 (Red Hat Linux)) id 1gsgfG-0003UV-82; Sun, 10 Feb 2019 04:24:27 +0000 Date: Sun, 10 Feb 2019 04:24:22 +0000 From: Al Viro To: netdev@vger.kernel.org Cc: Solar Designer , David Miller Subject: [RFC] apparently bogus logics in unix_find_other() since 2002 Message-ID: <20190210042414.GH2217@ZenIV.linux.org.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In "net/unix/af_unix.c: Set ATIME on socket inode" (back in 2002) we'd grown something rather odd in unix_find_other(). In the original patch it was u=unix_find_socket_byname(sunname, len, type, hash); - if (!u) + if (u) { + struct dentry *dentry; + dentry = u->protinfo.af_unix.dentry; + if (dentry) + UPDATE_ATIME(dentry->d_inode); + } else goto fail; These days the code is u = unix_find_socket_byname(net, sunname, len, type, hash); if (u) { struct dentry *dentry; dentry = unix_sk(u)->path.dentry; if (dentry) touch_atime(&unix_sk(u)->path); } else goto fail; but the logics is the same. It's the abstract address case - we have '\0' in sunname->sun_path[0]. How in hell could that possibly have non-NULL ->path.dentry and what would it be? Note that unix_find_socket_byname() returns non-NULL u here only if u->addr->name->sun_path[0] is equal to sunname->sun_path[0], i.e. '\0'. There are only two places where we ever might assign non-NULL to ->path.dentry: if (sun_path[0]) { addr->hash = UNIX_HASH_SIZE; hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1); spin_lock(&unix_table_lock); u->path = path; list = &unix_socket_table[hash]; } else { in unix_bind() (in which case u->addr->name->sun_path[0] will not be '\0') and /* copy address information from listening to new sock*/ if (otheru->addr) { refcount_inc(&otheru->addr->refcnt); newu->addr = otheru->addr; } if (otheru->path.dentry) { path_get(&otheru->path); newu->path = otheru->path; } in unix_stream_connect(). And once ->addr is non-NULL, it's never changed, and ->addr->name contents is never modified afterwards. So we would have to had the same condition (non-NULL ->path.dentry with '\0' in ->addr->name->sun_path[0]) at earlier point on the listener socket. Looks like that should be impossible; what am I missing here? Incidentally, how can the quoted fragment in in unix_stream_connect() be reached with NULL otheru->addr? After all, otheru is unix_sock of a listener; how could we possibly have found it if it had NULL ->addr? Confused...