Merge pull request #1559 from Mashimiao/panic-fix-nil-linux

fix panic when Linux is nil for rootless case
diff --git a/libcontainer/specconv/spec_linux.go b/libcontainer/specconv/spec_linux.go
index 128c766..8c3ba00 100644
--- a/libcontainer/specconv/spec_linux.go
+++ b/libcontainer/specconv/spec_linux.go
@@ -236,7 +236,6 @@
 	if spec.Process.SelinuxLabel != "" {
 		config.ProcessLabel = spec.Process.SelinuxLabel
 	}
-	config.Sysctl = spec.Linux.Sysctl
 	if spec.Process != nil && spec.Process.OOMScoreAdj != nil {
 		config.OomScoreAdj = *spec.Process.OOMScoreAdj
 	}
@@ -321,164 +320,163 @@
 	// the user didn't specify.
 	if !opts.Rootless {
 		c.Resources.AllowedDevices = allowedDevices
-		if spec.Linux == nil {
+	}
+	if spec.Linux != nil {
+		r := spec.Linux.Resources
+		if r == nil {
 			return c, nil
 		}
-	}
-	r := spec.Linux.Resources
-	if r == nil {
-		return c, nil
-	}
-	for i, d := range spec.Linux.Resources.Devices {
-		var (
-			t     = "a"
-			major = int64(-1)
-			minor = int64(-1)
-		)
-		if d.Type != "" {
-			t = d.Type
+		for i, d := range spec.Linux.Resources.Devices {
+			var (
+				t     = "a"
+				major = int64(-1)
+				minor = int64(-1)
+			)
+			if d.Type != "" {
+				t = d.Type
+			}
+			if d.Major != nil {
+				major = *d.Major
+			}
+			if d.Minor != nil {
+				minor = *d.Minor
+			}
+			if d.Access == "" {
+				return nil, fmt.Errorf("device access at %d field cannot be empty", i)
+			}
+			dt, err := stringToCgroupDeviceRune(t)
+			if err != nil {
+				return nil, err
+			}
+			dd := &configs.Device{
+				Type:        dt,
+				Major:       major,
+				Minor:       minor,
+				Permissions: d.Access,
+				Allow:       d.Allow,
+			}
+			c.Resources.Devices = append(c.Resources.Devices, dd)
 		}
-		if d.Major != nil {
-			major = *d.Major
+		if r.Memory != nil {
+			if r.Memory.Limit != nil {
+				c.Resources.Memory = *r.Memory.Limit
+			}
+			if r.Memory.Reservation != nil {
+				c.Resources.MemoryReservation = *r.Memory.Reservation
+			}
+			if r.Memory.Swap != nil {
+				c.Resources.MemorySwap = *r.Memory.Swap
+			}
+			if r.Memory.Kernel != nil {
+				c.Resources.KernelMemory = *r.Memory.Kernel
+			}
+			if r.Memory.KernelTCP != nil {
+				c.Resources.KernelMemoryTCP = *r.Memory.KernelTCP
+			}
+			if r.Memory.Swappiness != nil {
+				c.Resources.MemorySwappiness = r.Memory.Swappiness
+			}
+			if r.Memory.DisableOOMKiller != nil {
+				c.Resources.OomKillDisable = *r.Memory.DisableOOMKiller
+			}
 		}
-		if d.Minor != nil {
-			minor = *d.Minor
+		if r.CPU != nil {
+			if r.CPU.Shares != nil {
+				c.Resources.CpuShares = *r.CPU.Shares
+			}
+			if r.CPU.Quota != nil {
+				c.Resources.CpuQuota = *r.CPU.Quota
+			}
+			if r.CPU.Period != nil {
+				c.Resources.CpuPeriod = *r.CPU.Period
+			}
+			if r.CPU.RealtimeRuntime != nil {
+				c.Resources.CpuRtRuntime = *r.CPU.RealtimeRuntime
+			}
+			if r.CPU.RealtimePeriod != nil {
+				c.Resources.CpuRtPeriod = *r.CPU.RealtimePeriod
+			}
+			if r.CPU.Cpus != "" {
+				c.Resources.CpusetCpus = r.CPU.Cpus
+			}
+			if r.CPU.Mems != "" {
+				c.Resources.CpusetMems = r.CPU.Mems
+			}
 		}
-		if d.Access == "" {
-			return nil, fmt.Errorf("device access at %d field cannot be empty", i)
+		if r.Pids != nil {
+			c.Resources.PidsLimit = r.Pids.Limit
 		}
-		dt, err := stringToCgroupDeviceRune(t)
-		if err != nil {
-			return nil, err
+		if r.BlockIO != nil {
+			if r.BlockIO.Weight != nil {
+				c.Resources.BlkioWeight = *r.BlockIO.Weight
+			}
+			if r.BlockIO.LeafWeight != nil {
+				c.Resources.BlkioLeafWeight = *r.BlockIO.LeafWeight
+			}
+			if r.BlockIO.WeightDevice != nil {
+				for _, wd := range r.BlockIO.WeightDevice {
+					var weight, leafWeight uint16
+					if wd.Weight != nil {
+						weight = *wd.Weight
+					}
+					if wd.LeafWeight != nil {
+						leafWeight = *wd.LeafWeight
+					}
+					weightDevice := configs.NewWeightDevice(wd.Major, wd.Minor, weight, leafWeight)
+					c.Resources.BlkioWeightDevice = append(c.Resources.BlkioWeightDevice, weightDevice)
+				}
+			}
+			if r.BlockIO.ThrottleReadBpsDevice != nil {
+				for _, td := range r.BlockIO.ThrottleReadBpsDevice {
+					rate := td.Rate
+					throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
+					c.Resources.BlkioThrottleReadBpsDevice = append(c.Resources.BlkioThrottleReadBpsDevice, throttleDevice)
+				}
+			}
+			if r.BlockIO.ThrottleWriteBpsDevice != nil {
+				for _, td := range r.BlockIO.ThrottleWriteBpsDevice {
+					rate := td.Rate
+					throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
+					c.Resources.BlkioThrottleWriteBpsDevice = append(c.Resources.BlkioThrottleWriteBpsDevice, throttleDevice)
+				}
+			}
+			if r.BlockIO.ThrottleReadIOPSDevice != nil {
+				for _, td := range r.BlockIO.ThrottleReadIOPSDevice {
+					rate := td.Rate
+					throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
+					c.Resources.BlkioThrottleReadIOPSDevice = append(c.Resources.BlkioThrottleReadIOPSDevice, throttleDevice)
+				}
+			}
+			if r.BlockIO.ThrottleWriteIOPSDevice != nil {
+				for _, td := range r.BlockIO.ThrottleWriteIOPSDevice {
+					rate := td.Rate
+					throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
+					c.Resources.BlkioThrottleWriteIOPSDevice = append(c.Resources.BlkioThrottleWriteIOPSDevice, throttleDevice)
+				}
+			}
 		}
-		dd := &configs.Device{
-			Type:        dt,
-			Major:       major,
-			Minor:       minor,
-			Permissions: d.Access,
-			Allow:       d.Allow,
+		for _, l := range r.HugepageLimits {
+			c.Resources.HugetlbLimit = append(c.Resources.HugetlbLimit, &configs.HugepageLimit{
+				Pagesize: l.Pagesize,
+				Limit:    l.Limit,
+			})
 		}
-		c.Resources.Devices = append(c.Resources.Devices, dd)
+		if r.Network != nil {
+			if r.Network.ClassID != nil {
+				c.Resources.NetClsClassid = *r.Network.ClassID
+			}
+			for _, m := range r.Network.Priorities {
+				c.Resources.NetPrioIfpriomap = append(c.Resources.NetPrioIfpriomap, &configs.IfPrioMap{
+					Interface: m.Name,
+					Priority:  int64(m.Priority),
+				})
+			}
+		}
 	}
 	if !opts.Rootless {
 		// append the default allowed devices to the end of the list
 		c.Resources.Devices = append(c.Resources.Devices, allowedDevices...)
 	}
-	if r.Memory != nil {
-		if r.Memory.Limit != nil {
-			c.Resources.Memory = *r.Memory.Limit
-		}
-		if r.Memory.Reservation != nil {
-			c.Resources.MemoryReservation = *r.Memory.Reservation
-		}
-		if r.Memory.Swap != nil {
-			c.Resources.MemorySwap = *r.Memory.Swap
-		}
-		if r.Memory.Kernel != nil {
-			c.Resources.KernelMemory = *r.Memory.Kernel
-		}
-		if r.Memory.KernelTCP != nil {
-			c.Resources.KernelMemoryTCP = *r.Memory.KernelTCP
-		}
-		if r.Memory.Swappiness != nil {
-			c.Resources.MemorySwappiness = r.Memory.Swappiness
-		}
-		if r.Memory.DisableOOMKiller != nil {
-			c.Resources.OomKillDisable = *r.Memory.DisableOOMKiller
-		}
-	}
-	if r.CPU != nil {
-		if r.CPU.Shares != nil {
-			c.Resources.CpuShares = *r.CPU.Shares
-		}
-		if r.CPU.Quota != nil {
-			c.Resources.CpuQuota = *r.CPU.Quota
-		}
-		if r.CPU.Period != nil {
-			c.Resources.CpuPeriod = *r.CPU.Period
-		}
-		if r.CPU.RealtimeRuntime != nil {
-			c.Resources.CpuRtRuntime = *r.CPU.RealtimeRuntime
-		}
-		if r.CPU.RealtimePeriod != nil {
-			c.Resources.CpuRtPeriod = *r.CPU.RealtimePeriod
-		}
-		if r.CPU.Cpus != "" {
-			c.Resources.CpusetCpus = r.CPU.Cpus
-		}
-		if r.CPU.Mems != "" {
-			c.Resources.CpusetMems = r.CPU.Mems
-		}
-	}
-	if r.Pids != nil {
-		c.Resources.PidsLimit = r.Pids.Limit
-	}
-	if r.BlockIO != nil {
-		if r.BlockIO.Weight != nil {
-			c.Resources.BlkioWeight = *r.BlockIO.Weight
-		}
-		if r.BlockIO.LeafWeight != nil {
-			c.Resources.BlkioLeafWeight = *r.BlockIO.LeafWeight
-		}
-		if r.BlockIO.WeightDevice != nil {
-			for _, wd := range r.BlockIO.WeightDevice {
-				var weight, leafWeight uint16
-				if wd.Weight != nil {
-					weight = *wd.Weight
-				}
-				if wd.LeafWeight != nil {
-					leafWeight = *wd.LeafWeight
-				}
-				weightDevice := configs.NewWeightDevice(wd.Major, wd.Minor, weight, leafWeight)
-				c.Resources.BlkioWeightDevice = append(c.Resources.BlkioWeightDevice, weightDevice)
-			}
-		}
-		if r.BlockIO.ThrottleReadBpsDevice != nil {
-			for _, td := range r.BlockIO.ThrottleReadBpsDevice {
-				rate := td.Rate
-				throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
-				c.Resources.BlkioThrottleReadBpsDevice = append(c.Resources.BlkioThrottleReadBpsDevice, throttleDevice)
-			}
-		}
-		if r.BlockIO.ThrottleWriteBpsDevice != nil {
-			for _, td := range r.BlockIO.ThrottleWriteBpsDevice {
-				rate := td.Rate
-				throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
-				c.Resources.BlkioThrottleWriteBpsDevice = append(c.Resources.BlkioThrottleWriteBpsDevice, throttleDevice)
-			}
-		}
-		if r.BlockIO.ThrottleReadIOPSDevice != nil {
-			for _, td := range r.BlockIO.ThrottleReadIOPSDevice {
-				rate := td.Rate
-				throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
-				c.Resources.BlkioThrottleReadIOPSDevice = append(c.Resources.BlkioThrottleReadIOPSDevice, throttleDevice)
-			}
-		}
-		if r.BlockIO.ThrottleWriteIOPSDevice != nil {
-			for _, td := range r.BlockIO.ThrottleWriteIOPSDevice {
-				rate := td.Rate
-				throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
-				c.Resources.BlkioThrottleWriteIOPSDevice = append(c.Resources.BlkioThrottleWriteIOPSDevice, throttleDevice)
-			}
-		}
-	}
-	for _, l := range r.HugepageLimits {
-		c.Resources.HugetlbLimit = append(c.Resources.HugetlbLimit, &configs.HugepageLimit{
-			Pagesize: l.Pagesize,
-			Limit:    l.Limit,
-		})
-	}
-	if r.Network != nil {
-		if r.Network.ClassID != nil {
-			c.Resources.NetClsClassid = *r.Network.ClassID
-		}
-		for _, m := range r.Network.Priorities {
-			c.Resources.NetPrioIfpriomap = append(c.Resources.NetPrioIfpriomap, &configs.IfPrioMap{
-				Interface: m.Name,
-				Priority:  int64(m.Priority),
-			})
-		}
-	}
 	return c, nil
 }