lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Sun, 28 May 2017 05:57:01 +0800
From:   kbuild test robot <lkp@...el.com>
To:     Kees Cook <keescook@...omium.org>
Cc:     kbuild-all@...org, linux-kernel@...r.kernel.org,
        Andrew Morton <akpm@...ux-foundation.org>,
        David Windsor <dwindsor@...il.com>,
        Kees Cook <keescook@...omium.org>,
        Hans Liljestrand <ishkamiel@...il.com>,
        Elena Reshetova <elena.reshetova@...el.com>,
        Davidlohr Bueso <dave@...olabs.net>,
        Manfred Spraul <manfred@...orfullife.com>,
        Mauro Carvalho Chehab <mchehab@...nel.org>,
        Bjorn Helgaas <bhelgaas@...gle.com>,
        Michal Hocko <mhocko@...e.com>
Subject: Re: [PATCH] ipc: Convert kern_ipc_perm.refcount to refcount_t

Hi Elena,

[auto build test ERROR on next-20170526]
[cannot apply to linus/master linux/master kees/for-next/pstore v4.9-rc8 v4.9-rc7 v4.9-rc6 v4.12-rc2]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Kees-Cook/ipc-Convert-kern_ipc_perm-refcount-to-refcount_t/20170528-040601
config: m32r-m32104ut_defconfig (attached as .config)
compiler: m32r-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=m32r 

All errors (new ones prefixed by >>):

   In file included from include/uapi/linux/shm.h:4:0,
                    from include/linux/shm.h:6,
                    from ipc/util.c:44:
   include/linux/ipc.h:25:2: error: unknown type name 'refcount_t'
     refcount_t refcount;
     ^~~~~~~~~~
   ipc/util.c: In function 'ipc_addid':
>> ipc/util.c:235:15: error: passing argument 1 of 'refcount_set' from incompatible pointer type [-Werror=incompatible-pointer-types]
     refcount_set(&new->refcount, 1);
                  ^
   In file included from include/linux/key.h:26:0,
                    from include/linux/security.h:26,
                    from ipc/util.c:52:
   include/linux/refcount.h:28:20: note: expected 'refcount_t * {aka struct refcount_struct *}' but argument is of type 'int *'
    static inline void refcount_set(refcount_t *r, unsigned int n)
                       ^~~~~~~~~~~~
   ipc/util.c: In function 'ipc_rcu_getref':
>> ipc/util.c:400:31: error: passing argument 1 of 'refcount_inc_not_zero' from incompatible pointer type [-Werror=incompatible-pointer-types]
     return refcount_inc_not_zero(&ptr->refcount);
                                  ^
   In file included from include/linux/key.h:26:0,
                    from include/linux/security.h:26,
                    from ipc/util.c:52:
   include/linux/refcount.h:47:26: note: expected 'refcount_t * {aka struct refcount_struct *}' but argument is of type 'int *'
    extern __must_check bool refcount_inc_not_zero(refcount_t *r);
                             ^~~~~~~~~~~~~~~~~~~~~
   ipc/util.c: In function 'ipc_rcu_putref':
>> ipc/util.c:406:29: error: passing argument 1 of 'refcount_dec_and_test' from incompatible pointer type [-Werror=incompatible-pointer-types]
     if (!refcount_dec_and_test(&ptr->refcount))
                                ^
   In file included from include/linux/key.h:26:0,
                    from include/linux/security.h:26,
                    from ipc/util.c:52:
   include/linux/refcount.h:53:26: note: expected 'refcount_t * {aka struct refcount_struct *}' but argument is of type 'int *'
    extern __must_check bool refcount_dec_and_test(refcount_t *r);
                             ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/refcount_set +235 ipc/util.c

    38	 *
    39	 *  Note that sems have a special fast path that avoids kern_ipc_perm.lock -
    40	 *  see sem_lock().
    41	 */
    42	
    43	#include <linux/mm.h>
  > 44	#include <linux/shm.h>
    45	#include <linux/init.h>
    46	#include <linux/msg.h>
    47	#include <linux/vmalloc.h>
    48	#include <linux/slab.h>
    49	#include <linux/notifier.h>
    50	#include <linux/capability.h>
    51	#include <linux/highuid.h>
  > 52	#include <linux/security.h>
    53	#include <linux/rcupdate.h>
    54	#include <linux/workqueue.h>
    55	#include <linux/seq_file.h>
    56	#include <linux/proc_fs.h>
    57	#include <linux/audit.h>
    58	#include <linux/nsproxy.h>
    59	#include <linux/rwsem.h>
    60	#include <linux/memory.h>
    61	#include <linux/ipc_namespace.h>
    62	
    63	#include <asm/unistd.h>
    64	
    65	#include "util.h"
    66	
    67	struct ipc_proc_iface {
    68		const char *path;
    69		const char *header;
    70		int ids;
    71		int (*show)(struct seq_file *, void *);
    72	};
    73	
    74	/**
    75	 * ipc_init - initialise ipc subsystem
    76	 *
    77	 * The various sysv ipc resources (semaphores, messages and shared
    78	 * memory) are initialised.
    79	 *
    80	 * A callback routine is registered into the memory hotplug notifier
    81	 * chain: since msgmni scales to lowmem this callback routine will be
    82	 * called upon successful memory add / remove to recompute msmgni.
    83	 */
    84	static int __init ipc_init(void)
    85	{
    86		sem_init();
    87		msg_init();
    88		shm_init();
    89		return 0;
    90	}
    91	device_initcall(ipc_init);
    92	
    93	/**
    94	 * ipc_init_ids	- initialise ipc identifiers
    95	 * @ids: ipc identifier set
    96	 *
    97	 * Set up the sequence range to use for the ipc identifier range (limited
    98	 * below IPCMNI) then initialise the ids idr.
    99	 */
   100	void ipc_init_ids(struct ipc_ids *ids)
   101	{
   102		ids->in_use = 0;
   103		ids->seq = 0;
   104		ids->next_id = -1;
   105		init_rwsem(&ids->rwsem);
   106		idr_init(&ids->ipcs_idr);
   107	}
   108	
   109	#ifdef CONFIG_PROC_FS
   110	static const struct file_operations sysvipc_proc_fops;
   111	/**
   112	 * ipc_init_proc_interface -  create a proc interface for sysipc types using a seq_file interface.
   113	 * @path: Path in procfs
   114	 * @header: Banner to be printed at the beginning of the file.
   115	 * @ids: ipc id table to iterate.
   116	 * @show: show routine.
   117	 */
   118	void __init ipc_init_proc_interface(const char *path, const char *header,
   119			int ids, int (*show)(struct seq_file *, void *))
   120	{
   121		struct proc_dir_entry *pde;
   122		struct ipc_proc_iface *iface;
   123	
   124		iface = kmalloc(sizeof(*iface), GFP_KERNEL);
   125		if (!iface)
   126			return;
   127		iface->path	= path;
   128		iface->header	= header;
   129		iface->ids	= ids;
   130		iface->show	= show;
   131	
   132		pde = proc_create_data(path,
   133				       S_IRUGO,        /* world readable */
   134				       NULL,           /* parent dir */
   135				       &sysvipc_proc_fops,
   136				       iface);
   137		if (!pde)
   138			kfree(iface);
   139	}
   140	#endif
   141	
   142	/**
   143	 * ipc_findkey	- find a key in an ipc identifier set
   144	 * @ids: ipc identifier set
   145	 * @key: key to find
   146	 *
   147	 * Returns the locked pointer to the ipc structure if found or NULL
   148	 * otherwise. If key is found ipc points to the owning ipc structure
   149	 *
   150	 * Called with ipc_ids.rwsem held.
   151	 */
   152	static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
   153	{
   154		struct kern_ipc_perm *ipc;
   155		int next_id;
   156		int total;
   157	
   158		for (total = 0, next_id = 0; total < ids->in_use; next_id++) {
   159			ipc = idr_find(&ids->ipcs_idr, next_id);
   160	
   161			if (ipc == NULL)
   162				continue;
   163	
   164			if (ipc->key != key) {
   165				total++;
   166				continue;
   167			}
   168	
   169			rcu_read_lock();
   170			ipc_lock_object(ipc);
   171			return ipc;
   172		}
   173	
   174		return NULL;
   175	}
   176	
   177	/**
   178	 * ipc_get_maxid - get the last assigned id
   179	 * @ids: ipc identifier set
   180	 *
   181	 * Called with ipc_ids.rwsem held.
   182	 */
   183	int ipc_get_maxid(struct ipc_ids *ids)
   184	{
   185		struct kern_ipc_perm *ipc;
   186		int max_id = -1;
   187		int total, id;
   188	
   189		if (ids->in_use == 0)
   190			return -1;
   191	
   192		if (ids->in_use == IPCMNI)
   193			return IPCMNI - 1;
   194	
   195		/* Look for the last assigned id */
   196		total = 0;
   197		for (id = 0; id < IPCMNI && total < ids->in_use; id++) {
   198			ipc = idr_find(&ids->ipcs_idr, id);
   199			if (ipc != NULL) {
   200				max_id = id;
   201				total++;
   202			}
   203		}
   204		return max_id;
   205	}
   206	
   207	/**
   208	 * ipc_addid - add an ipc identifier
   209	 * @ids: ipc identifier set
   210	 * @new: new ipc permission set
   211	 * @size: limit for the number of used ids
   212	 *
   213	 * Add an entry 'new' to the ipc ids idr. The permissions object is
   214	 * initialised and the first free entry is set up and the id assigned
   215	 * is returned. The 'new' entry is returned in a locked state on success.
   216	 * On failure the entry is not locked and a negative err-code is returned.
   217	 *
   218	 * Called with writer ipc_ids.rwsem held.
   219	 */
   220	int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size)
   221	{
   222		kuid_t euid;
   223		kgid_t egid;
   224		int id;
   225		int next_id = ids->next_id;
   226	
   227		if (size > IPCMNI)
   228			size = IPCMNI;
   229	
   230		if (ids->in_use >= size)
   231			return -ENOSPC;
   232	
   233		idr_preload(GFP_KERNEL);
   234	
 > 235		refcount_set(&new->refcount, 1);
   236		spin_lock_init(&new->lock);
   237		new->deleted = false;
   238		rcu_read_lock();
   239		spin_lock(&new->lock);
   240	
   241		current_euid_egid(&euid, &egid);
   242		new->cuid = new->uid = euid;
   243		new->gid = new->cgid = egid;
   244	
   245		id = idr_alloc(&ids->ipcs_idr, new,
   246			       (next_id < 0) ? 0 : ipcid_to_idx(next_id), 0,
   247			       GFP_NOWAIT);
   248		idr_preload_end();
   249		if (id < 0) {
   250			spin_unlock(&new->lock);
   251			rcu_read_unlock();
   252			return id;
   253		}
   254	
   255		ids->in_use++;
   256	
   257		if (next_id < 0) {
   258			new->seq = ids->seq++;
   259			if (ids->seq > IPCID_SEQ_MAX)
   260				ids->seq = 0;
   261		} else {
   262			new->seq = ipcid_to_seqx(next_id);
   263			ids->next_id = -1;
   264		}
   265	
   266		new->id = ipc_buildid(id, new->seq);
   267		return id;
   268	}
   269	
   270	/**
   271	 * ipcget_new -	create a new ipc object
   272	 * @ns: ipc namespace
   273	 * @ids: ipc identifier set
   274	 * @ops: the actual creation routine to call
   275	 * @params: its parameters
   276	 *
   277	 * This routine is called by sys_msgget, sys_semget() and sys_shmget()
   278	 * when the key is IPC_PRIVATE.
   279	 */
   280	static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
   281			const struct ipc_ops *ops, struct ipc_params *params)
   282	{
   283		int err;
   284	
   285		down_write(&ids->rwsem);
   286		err = ops->getnew(ns, params);
   287		up_write(&ids->rwsem);
   288		return err;
   289	}
   290	
   291	/**
   292	 * ipc_check_perms - check security and permissions for an ipc object
   293	 * @ns: ipc namespace
   294	 * @ipcp: ipc permission set
   295	 * @ops: the actual security routine to call
   296	 * @params: its parameters
   297	 *
   298	 * This routine is called by sys_msgget(), sys_semget() and sys_shmget()
   299	 * when the key is not IPC_PRIVATE and that key already exists in the
   300	 * ds IDR.
   301	 *
   302	 * On success, the ipc id is returned.
   303	 *
   304	 * It is called with ipc_ids.rwsem and ipcp->lock held.
   305	 */
   306	static int ipc_check_perms(struct ipc_namespace *ns,
   307				   struct kern_ipc_perm *ipcp,
   308				   const struct ipc_ops *ops,
   309				   struct ipc_params *params)
   310	{
   311		int err;
   312	
   313		if (ipcperms(ns, ipcp, params->flg))
   314			err = -EACCES;
   315		else {
   316			err = ops->associate(ipcp, params->flg);
   317			if (!err)
   318				err = ipcp->id;
   319		}
   320	
   321		return err;
   322	}
   323	
   324	/**
   325	 * ipcget_public - get an ipc object or create a new one
   326	 * @ns: ipc namespace
   327	 * @ids: ipc identifier set
   328	 * @ops: the actual creation routine to call
   329	 * @params: its parameters
   330	 *
   331	 * This routine is called by sys_msgget, sys_semget() and sys_shmget()
   332	 * when the key is not IPC_PRIVATE.
   333	 * It adds a new entry if the key is not found and does some permission
   334	 * / security checkings if the key is found.
   335	 *
   336	 * On success, the ipc id is returned.
   337	 */
   338	static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
   339			const struct ipc_ops *ops, struct ipc_params *params)
   340	{
   341		struct kern_ipc_perm *ipcp;
   342		int flg = params->flg;
   343		int err;
   344	
   345		/*
   346		 * Take the lock as a writer since we are potentially going to add
   347		 * a new entry + read locks are not "upgradable"
   348		 */
   349		down_write(&ids->rwsem);
   350		ipcp = ipc_findkey(ids, params->key);
   351		if (ipcp == NULL) {
   352			/* key not used */
   353			if (!(flg & IPC_CREAT))
   354				err = -ENOENT;
   355			else
   356				err = ops->getnew(ns, params);
   357		} else {
   358			/* ipc object has been locked by ipc_findkey() */
   359	
   360			if (flg & IPC_CREAT && flg & IPC_EXCL)
   361				err = -EEXIST;
   362			else {
   363				err = 0;
   364				if (ops->more_checks)
   365					err = ops->more_checks(ipcp, params);
   366				if (!err)
   367					/*
   368					 * ipc_check_perms returns the IPC id on
   369					 * success
   370					 */
   371					err = ipc_check_perms(ns, ipcp, ops, params);
   372			}
   373			ipc_unlock(ipcp);
   374		}
   375		up_write(&ids->rwsem);
   376	
   377		return err;
   378	}
   379	
   380	
   381	/**
   382	 * ipc_rmid - remove an ipc identifier
   383	 * @ids: ipc identifier set
   384	 * @ipcp: ipc perm structure containing the identifier to remove
   385	 *
   386	 * ipc_ids.rwsem (as a writer) and the spinlock for this ID are held
   387	 * before this function is called, and remain locked on the exit.
   388	 */
   389	void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
   390	{
   391		int lid = ipcid_to_idx(ipcp->id);
   392	
   393		idr_remove(&ids->ipcs_idr, lid);
   394		ids->in_use--;
   395		ipcp->deleted = true;
   396	}
   397	
   398	int ipc_rcu_getref(struct kern_ipc_perm *ptr)
   399	{
 > 400		return refcount_inc_not_zero(&ptr->refcount);
   401	}
   402	
   403	void ipc_rcu_putref(struct kern_ipc_perm *ptr,
   404				void (*func)(struct rcu_head *head))
   405	{
 > 406		if (!refcount_dec_and_test(&ptr->refcount))
   407			return;
   408	
   409		call_rcu(&ptr->rcu, func);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Download attachment ".config.gz" of type "application/gzip" (11266 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ