CVE-2017-15288
This commit is contained in:
parent
b8601533d7
commit
4380af6452
277
CVE-2017-15288-pre.patch
Normal file
277
CVE-2017-15288-pre.patch
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
From caa9ebc482969a884da5f9c9c246470811b8599d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Teemu Lehtinen <teemu.t.lehtinen@aalto.fi>
|
||||||
|
Date: Wed, 20 Aug 2014 13:20:41 +0300
|
||||||
|
Subject: [PATCH] Add option -port to fsc
|
||||||
|
|
||||||
|
Option "port" limits compile server lookup and start to given port.
|
||||||
|
Normally fsc will start a compile server in a random port if no server
|
||||||
|
is yet running. This can be problematic with firewalls and/or remote
|
||||||
|
compile servers. Option "port" should not be confused with option
|
||||||
|
"server" which looks for a compile server in given host and port and
|
||||||
|
fails if such server is not found.
|
||||||
|
|
||||||
|
Automatic tests for command line user interface do not exist at all.
|
||||||
|
Thus, adding a test for one new option would require designing a whole
|
||||||
|
new testing method.
|
||||||
|
|
||||||
|
Cherry picked from 7daecd8
|
||||||
|
---
|
||||||
|
.../scala/tools/nsc/CompileClient.scala | 4 +-
|
||||||
|
.../scala/tools/nsc/CompileServer.scala | 56 ++++++++++++-------
|
||||||
|
.../scala/tools/nsc/CompileSocket.scala | 37 +++++++-----
|
||||||
|
.../tools/nsc/settings/FscSettings.scala | 4 +-
|
||||||
|
.../scala/tools/util/SocketServer.scala | 4 +-
|
||||||
|
5 files changed, 65 insertions(+), 40 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/CompileClient.scala b/src/compiler/scala/tools/nsc/CompileClient.scala
|
||||||
|
index 731f6926f00..842d6ac535b 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/CompileClient.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/CompileClient.scala
|
||||||
|
@@ -43,8 +43,8 @@ class StandardCompileClient extends HasCompileSocket with CompileOutputCommon {
|
||||||
|
info(vmArgs.mkString("[VM arguments: ", " ", "]"))
|
||||||
|
|
||||||
|
val socket =
|
||||||
|
- if (settings.server.value == "") compileSocket.getOrCreateSocket(vmArgs mkString " ", !shutdown)
|
||||||
|
- else Some(compileSocket.getSocket(settings.server.value))
|
||||||
|
+ if (settings.server.value == "") compileSocket.getOrCreateSocket(vmArgs mkString " ", !shutdown, settings.port.value)
|
||||||
|
+ else compileSocket.getSocket(settings.server.value)
|
||||||
|
|
||||||
|
socket match {
|
||||||
|
case Some(sock) => compileOnServer(sock, fscArgs)
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
|
||||||
|
index 7a0a072bb8d..6352d75686a 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
|
||||||
|
@@ -5,11 +5,13 @@
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
|
||||||
|
-import java.io.{ BufferedOutputStream, FileOutputStream, PrintStream }
|
||||||
|
-import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
|
||||||
|
-import scala.reflect.internal.util.FakePos //Position
|
||||||
|
+import java.io.PrintStream
|
||||||
|
+
|
||||||
|
+import scala.reflect.internal.util.FakePos
|
||||||
|
+import scala.tools.nsc.io.Directory
|
||||||
|
+import scala.tools.nsc.reporters.{ConsoleReporter, Reporter}
|
||||||
|
+import scala.tools.nsc.settings.FscSettings
|
||||||
|
import scala.tools.util.SocketServer
|
||||||
|
-import settings.FscSettings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server part of the fsc offline compiler. It awaits compilation
|
||||||
|
@@ -19,7 +21,7 @@ import settings.FscSettings
|
||||||
|
* @author Martin Odersky
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
-class StandardCompileServer extends SocketServer {
|
||||||
|
+class StandardCompileServer(fixPort: Int = 0) extends SocketServer(fixPort) {
|
||||||
|
lazy val compileSocket: CompileSocket = CompileSocket
|
||||||
|
|
||||||
|
private var compiler: Global = null
|
||||||
|
@@ -34,7 +36,7 @@ class StandardCompileServer extends SocketServer {
|
||||||
|
val MaxCharge = 0.8
|
||||||
|
|
||||||
|
private val runtime = Runtime.getRuntime()
|
||||||
|
- import runtime.{ totalMemory, freeMemory, maxMemory }
|
||||||
|
+ import runtime.{freeMemory, maxMemory, totalMemory}
|
||||||
|
|
||||||
|
/** Create a new compiler instance */
|
||||||
|
def newGlobal(settings: Settings, reporter: Reporter) =
|
||||||
|
@@ -170,16 +172,16 @@ class StandardCompileServer extends SocketServer {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-object CompileServer extends StandardCompileServer {
|
||||||
|
+object CompileServer {
|
||||||
|
/** A directory holding redirected output */
|
||||||
|
- private lazy val redirectDir = (compileSocket.tmpDir / "output-redirects").createDirectory()
|
||||||
|
+ //private lazy val redirectDir = (compileSocket.tmpDir / "output-redirects").createDirectory()
|
||||||
|
|
||||||
|
- private def createRedirect(filename: String) =
|
||||||
|
- new PrintStream((redirectDir / filename).createFile().bufferedOutput())
|
||||||
|
+ private def createRedirect(dir: Directory, filename: String) =
|
||||||
|
+ new PrintStream((dir / filename).createFile().bufferedOutput())
|
||||||
|
|
||||||
|
- def main(args: Array[String]) =
|
||||||
|
+ def main(args: Array[String]) =
|
||||||
|
execute(() => (), args)
|
||||||
|
-
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* Used for internal testing. The callback is called upon
|
||||||
|
* server start, notifying the caller that the server is
|
||||||
|
@@ -191,21 +193,33 @@ object CompileServer extends StandardCompileServer {
|
||||||
|
*/
|
||||||
|
def execute(startupCallback : () => Unit, args: Array[String]) {
|
||||||
|
val debug = args contains "-v"
|
||||||
|
+ var port = 0
|
||||||
|
+
|
||||||
|
+ val i = args.indexOf("-p")
|
||||||
|
+ if (i >= 0 && args.length > i + 1) {
|
||||||
|
+ scala.util.control.Exception.ignoring(classOf[NumberFormatException]) {
|
||||||
|
+ port = args(i + 1).toInt
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Create instance rather than extend to pass a port parameter.
|
||||||
|
+ val server = new StandardCompileServer(port)
|
||||||
|
+ val redirectDir = (server.compileSocket.tmpDir / "output-redirects").createDirectory()
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
- echo("Starting CompileServer on port " + port)
|
||||||
|
- echo("Redirect dir is " + redirectDir)
|
||||||
|
+ server.echo("Starting CompileServer on port " + server.port)
|
||||||
|
+ server.echo("Redirect dir is " + redirectDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
- Console.withErr(createRedirect("scala-compile-server-err.log")) {
|
||||||
|
- Console.withOut(createRedirect("scala-compile-server-out.log")) {
|
||||||
|
- Console.err.println("...starting server on socket "+port+"...")
|
||||||
|
+ Console.withErr(createRedirect(redirectDir, "scala-compile-server-err.log")) {
|
||||||
|
+ Console.withOut(createRedirect(redirectDir, "scala-compile-server-out.log")) {
|
||||||
|
+ Console.err.println("...starting server on socket "+server.port+"...")
|
||||||
|
Console.err.flush()
|
||||||
|
- compileSocket setPort port
|
||||||
|
+ server.compileSocket setPort server.port
|
||||||
|
startupCallback()
|
||||||
|
- run()
|
||||||
|
-
|
||||||
|
- compileSocket deletePort port
|
||||||
|
+ server.run()
|
||||||
|
+
|
||||||
|
+ server.compileSocket deletePort server.port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala
|
||||||
|
index 4051bda9144..f5039b8303f 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/CompileSocket.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/CompileSocket.scala
|
||||||
|
@@ -5,16 +5,13 @@
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
|
||||||
|
-import java.io.{ IOException, FileNotFoundException, PrintWriter, FileOutputStream }
|
||||||
|
-import java.io.{ BufferedReader, FileReader }
|
||||||
|
-import java.util.regex.Pattern
|
||||||
|
-import java.net._
|
||||||
|
+import java.io.FileNotFoundException
|
||||||
|
import java.security.SecureRandom
|
||||||
|
-import io.{ File, Path, Directory, Socket }
|
||||||
|
-import scala.util.control.Exception.catching
|
||||||
|
-import scala.tools.util.CompileOutputCommon
|
||||||
|
+
|
||||||
|
import scala.reflect.internal.util.StringOps.splitWhere
|
||||||
|
import scala.sys.process._
|
||||||
|
+import scala.tools.nsc.io.{File, Path, Socket}
|
||||||
|
+import scala.tools.util.CompileOutputCommon
|
||||||
|
|
||||||
|
trait HasCompileSocket {
|
||||||
|
def compileSocket: CompileSocket
|
||||||
|
@@ -50,6 +47,9 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
protected lazy val compileClient: StandardCompileClient = CompileClient
|
||||||
|
def verbose = compileClient.verbose
|
||||||
|
|
||||||
|
+ /* Fixes the port where to start the server, 0 yields some free port */
|
||||||
|
+ var fixPort = 0
|
||||||
|
+
|
||||||
|
/** The prefix of the port identification file, which is followed
|
||||||
|
* by the port number.
|
||||||
|
*/
|
||||||
|
@@ -67,7 +67,7 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
|
||||||
|
/** The class name of the scala compile server */
|
||||||
|
protected val serverClass = "scala.tools.nsc.CompileServer"
|
||||||
|
- protected def serverClassArgs = if (verbose) List("-v") else Nil // debug
|
||||||
|
+ protected def serverClassArgs = (if (verbose) List("-v") else Nil) ::: (if (fixPort > 0) List("-p", fixPort.toString) else Nil)
|
||||||
|
|
||||||
|
/** A temporary directory to use */
|
||||||
|
val tmpDir = {
|
||||||
|
@@ -107,9 +107,14 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
def portFile(port: Int) = portsDir / File(port.toString)
|
||||||
|
|
||||||
|
/** Poll for a server port number; return -1 if none exists yet */
|
||||||
|
- private def pollPort(): Int = portsDir.list.toList match {
|
||||||
|
+ private def pollPort(): Int = if (fixPort > 0) {
|
||||||
|
+ if (portsDir.list.toList.exists(_.name == fixPort.toString)) fixPort else -1
|
||||||
|
+ } else portsDir.list.toList match {
|
||||||
|
case Nil => -1
|
||||||
|
- case x :: xs => try x.name.toInt finally xs foreach (_.delete())
|
||||||
|
+ case x :: xs => try x.name.toInt catch {
|
||||||
|
+ case e: Exception => x.delete()
|
||||||
|
+ throw e
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the port number to which a scala compile server is connected;
|
||||||
|
@@ -155,7 +160,8 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
* create a new daemon if necessary. Returns None if the connection
|
||||||
|
* cannot be established.
|
||||||
|
*/
|
||||||
|
- def getOrCreateSocket(vmArgs: String, create: Boolean = true): Option[Socket] = {
|
||||||
|
+ def getOrCreateSocket(vmArgs: String, create: Boolean = true, fixedPort: Int = 0): Option[Socket] = {
|
||||||
|
+ fixPort = fixedPort
|
||||||
|
val maxMillis = 10 * 1000 // try for 10 seconds
|
||||||
|
val retryDelay = 50
|
||||||
|
val maxAttempts = maxMillis / retryDelay
|
||||||
|
@@ -189,13 +195,16 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
try { Some(x.toInt) }
|
||||||
|
catch { case _: NumberFormatException => None }
|
||||||
|
|
||||||
|
- def getSocket(serverAdr: String): Socket = (
|
||||||
|
+ def getSocket(serverAdr: String): Option[Socket] = (
|
||||||
|
for ((name, portStr) <- splitWhere(serverAdr, _ == ':', true) ; port <- parseInt(portStr)) yield
|
||||||
|
getSocket(name, port)
|
||||||
|
) getOrElse fatal("Malformed server address: %s; exiting" format serverAdr)
|
||||||
|
|
||||||
|
- def getSocket(hostName: String, port: Int): Socket =
|
||||||
|
- Socket(hostName, port).opt getOrElse fatal("Unable to establish connection to server %s:%d; exiting".format(hostName, port))
|
||||||
|
+ def getSocket(hostName: String, port: Int): Option[Socket] = {
|
||||||
|
+ val sock = Socket(hostName, port).opt
|
||||||
|
+ if (sock.isEmpty) warn("Unable to establish connection to server %s:%d".format(hostName, port))
|
||||||
|
+ sock
|
||||||
|
+ }
|
||||||
|
|
||||||
|
def getPassword(port: Int): String = {
|
||||||
|
val ff = portFile(port)
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/settings/FscSettings.scala b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
|
||||||
|
index 5c852ae07c1..f5f971d697e 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/settings/FscSettings.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
|
||||||
|
@@ -22,13 +22,15 @@ class FscSettings(error: String => Unit) extends Settings(error) {
|
||||||
|
val reset = BooleanSetting("-reset", "Reset compile server caches")
|
||||||
|
val shutdown = BooleanSetting("-shutdown", "Shutdown compile server")
|
||||||
|
val server = StringSetting ("-server", "hostname:portnumber", "Specify compile server socket", "")
|
||||||
|
+ val port = IntSetting ("-port", "Search and start compile server in given port only",
|
||||||
|
+ 0, Some((0, Int.MaxValue)), (_: String) => None)
|
||||||
|
val preferIPv4 = BooleanSetting("-ipv4", "Use IPv4 rather than IPv6 for the server socket")
|
||||||
|
val idleMins = IntSetting ("-max-idle", "Set idle timeout in minutes for fsc (use 0 for no timeout)",
|
||||||
|
30, Some((0, Int.MaxValue)), (_: String) => None)
|
||||||
|
|
||||||
|
// For improved help output, separating fsc options from the others.
|
||||||
|
def fscSpecific = Set[Settings#Setting](
|
||||||
|
- currentDir, reset, shutdown, server, preferIPv4, idleMins
|
||||||
|
+ currentDir, reset, shutdown, server, port, preferIPv4, idleMins
|
||||||
|
)
|
||||||
|
val isFscSpecific: String => Boolean = fscSpecific map (_.name)
|
||||||
|
|
||||||
|
diff --git a/src/compiler/scala/tools/util/SocketServer.scala b/src/compiler/scala/tools/util/SocketServer.scala
|
||||||
|
index 1b06ce2ff2e..edbc7ecc554 100644
|
||||||
|
--- a/src/compiler/scala/tools/util/SocketServer.scala
|
||||||
|
+++ b/src/compiler/scala/tools/util/SocketServer.scala
|
||||||
|
@@ -27,12 +27,12 @@ trait CompileOutputCommon {
|
||||||
|
* @author Martin Odersky
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
-abstract class SocketServer extends CompileOutputCommon {
|
||||||
|
+abstract class SocketServer(fixPort: Int = 0) extends CompileOutputCommon {
|
||||||
|
def shutdown: Boolean
|
||||||
|
def session(): Unit
|
||||||
|
def timeout(): Unit = () // called after a timeout is detected for subclasses to cleanup
|
||||||
|
// a hook for subclasses
|
||||||
|
- protected def createServerSocket(): ServerSocket = new ServerSocket(0)
|
||||||
|
+ protected def createServerSocket(): ServerSocket = new ServerSocket(fixPort)
|
||||||
|
|
||||||
|
var in: BufferedReader = _
|
||||||
|
var out: PrintWriter = _
|
||||||
506
CVE-2017-15288.patch
Normal file
506
CVE-2017-15288.patch
Normal file
@ -0,0 +1,506 @@
|
|||||||
|
From 67e1437e55df6789d0883cb8846d12071de75c63 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jason Zaugg <jzaugg@gmail.com>
|
||||||
|
Date: Mon, 2 Oct 2017 10:06:55 +1000
|
||||||
|
Subject: [PATCH] Move compilation daemon portfile under `~/.scalac/`
|
||||||
|
|
||||||
|
Store the compilation daemon's administrativia (port file, redirection)
|
||||||
|
under `~/.scalac/`, instead of the less standard
|
||||||
|
`/tmp/scala-devel/${USER:shared}/scalac-compile-server-port`.
|
||||||
|
|
||||||
|
On creation, remove group- and other-permissions from these
|
||||||
|
private files, ditto for the repl's history file.
|
||||||
|
|
||||||
|
On Java 6 on Windows, opt in to compilation daemon using `-nc:false`.
|
||||||
|
|
||||||
|
Cherry picked from b64ad85, aa133c9, 2ceb09c
|
||||||
|
---
|
||||||
|
.../scala/tools/nsc/CompileServer.scala | 22 ++--
|
||||||
|
.../scala/tools/nsc/CompileSocket.scala | 68 ++++++-----
|
||||||
|
.../tools/nsc/GenericRunnerSettings.scala | 5 +-
|
||||||
|
src/compiler/scala/tools/nsc/Properties.scala | 5 +
|
||||||
|
.../scala/tools/nsc/ScriptRunner.scala | 20 +++-
|
||||||
|
.../session/FileBackedHistory.scala | 32 +++++-
|
||||||
|
.../tools/nsc/util/ScalaClassLoader.scala | 27 ++---
|
||||||
|
.../internal/util/OwnerOnlyChmod.scala | 107 ++++++++++++++++++
|
||||||
|
8 files changed, 221 insertions(+), 65 deletions(-)
|
||||||
|
create mode 100644 src/reflect/scala/reflect/internal/util/OwnerOnlyChmod.scala
|
||||||
|
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
|
||||||
|
index 6352d75686a..c454ba8b62b 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
|
||||||
|
@@ -183,14 +183,15 @@ object CompileServer {
|
||||||
|
execute(() => (), args)
|
||||||
|
|
||||||
|
/**
|
||||||
|
- * Used for internal testing. The callback is called upon
|
||||||
|
- * server start, notifying the caller that the server is
|
||||||
|
- * ready to run. WARNING: the callback runs in the
|
||||||
|
- * server's thread, blocking the server from doing any work
|
||||||
|
- * until the callback is finished. Callbacks should be kept
|
||||||
|
- * simple and clients should not try to interact with the
|
||||||
|
- * server while the callback is processing.
|
||||||
|
- */
|
||||||
|
+ * The server's main loop.
|
||||||
|
+ *
|
||||||
|
+ * `startupCallback` is used for internal testing; it's called upon server start,
|
||||||
|
+ * notifying the caller that the server is ready to run.
|
||||||
|
+ *
|
||||||
|
+ * WARNING: the callback runs in the server's thread, blocking the server from doing any work
|
||||||
|
+ * until the callback is finished. Callbacks should be kept simple and clients should not try to
|
||||||
|
+ * interact with the server while the callback is processing.
|
||||||
|
+ */
|
||||||
|
def execute(startupCallback : () => Unit, args: Array[String]) {
|
||||||
|
val debug = args contains "-v"
|
||||||
|
var port = 0
|
||||||
|
@@ -198,14 +199,13 @@ object CompileServer {
|
||||||
|
val i = args.indexOf("-p")
|
||||||
|
if (i >= 0 && args.length > i + 1) {
|
||||||
|
scala.util.control.Exception.ignoring(classOf[NumberFormatException]) {
|
||||||
|
- port = args(i + 1).toInt
|
||||||
|
+ port = args(i + 1).toInt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create instance rather than extend to pass a port parameter.
|
||||||
|
val server = new StandardCompileServer(port)
|
||||||
|
- val redirectDir = (server.compileSocket.tmpDir / "output-redirects").createDirectory()
|
||||||
|
-
|
||||||
|
+ val redirectDir = server.compileSocket.mkDaemonDir("fsc_redirects")
|
||||||
|
if (debug) {
|
||||||
|
server.echo("Starting CompileServer on port " + server.port)
|
||||||
|
server.echo("Redirect dir is " + redirectDir)
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala
|
||||||
|
index f5039b8303f..b73d251e9cc 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/CompileSocket.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/CompileSocket.scala
|
||||||
|
@@ -5,13 +5,17 @@
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
|
||||||
|
-import java.io.FileNotFoundException
|
||||||
|
+import java.math.BigInteger
|
||||||
|
import java.security.SecureRandom
|
||||||
|
|
||||||
|
+import scala.io.Codec
|
||||||
|
+import scala.reflect.internal.util.OwnerOnlyChmod
|
||||||
|
import scala.reflect.internal.util.StringOps.splitWhere
|
||||||
|
import scala.sys.process._
|
||||||
|
-import scala.tools.nsc.io.{File, Path, Socket}
|
||||||
|
+import scala.tools.nsc.Properties.scalacDir
|
||||||
|
+import scala.tools.nsc.io.{File, Socket}
|
||||||
|
import scala.tools.util.CompileOutputCommon
|
||||||
|
+import scala.util.control.NonFatal
|
||||||
|
|
||||||
|
trait HasCompileSocket {
|
||||||
|
def compileSocket: CompileSocket
|
||||||
|
@@ -46,14 +50,10 @@ trait HasCompileSocket {
|
||||||
|
class CompileSocket extends CompileOutputCommon {
|
||||||
|
protected lazy val compileClient: StandardCompileClient = CompileClient
|
||||||
|
def verbose = compileClient.verbose
|
||||||
|
-
|
||||||
|
+ def verbose_=(v: Boolean) = compileClient.verbose = v
|
||||||
|
/* Fixes the port where to start the server, 0 yields some free port */
|
||||||
|
var fixPort = 0
|
||||||
|
|
||||||
|
- /** The prefix of the port identification file, which is followed
|
||||||
|
- * by the port number.
|
||||||
|
- */
|
||||||
|
- protected lazy val dirName = "scalac-compile-server-port"
|
||||||
|
protected def cmdName = Properties.scalaCmd
|
||||||
|
|
||||||
|
/** The vm part of the command to start a new scala compile server */
|
||||||
|
@@ -69,20 +69,8 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
protected val serverClass = "scala.tools.nsc.CompileServer"
|
||||||
|
protected def serverClassArgs = (if (verbose) List("-v") else Nil) ::: (if (fixPort > 0) List("-p", fixPort.toString) else Nil)
|
||||||
|
|
||||||
|
- /** A temporary directory to use */
|
||||||
|
- val tmpDir = {
|
||||||
|
- val udir = Option(Properties.userName) getOrElse "shared"
|
||||||
|
- val f = (Path(Properties.tmpDir) / ("scala-devel" + udir)).createDirectory()
|
||||||
|
-
|
||||||
|
- if (f.isDirectory && f.canWrite) {
|
||||||
|
- info("[Temp directory: " + f + "]")
|
||||||
|
- f
|
||||||
|
- }
|
||||||
|
- else fatal("Could not find a directory for temporary files")
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
/* A directory holding port identification files */
|
||||||
|
- val portsDir = (tmpDir / dirName).createDirectory()
|
||||||
|
+ private lazy val portsDir = mkDaemonDir("fsc_port")
|
||||||
|
|
||||||
|
/** The command which starts the compile server, given vm arguments.
|
||||||
|
*
|
||||||
|
@@ -104,7 +92,7 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The port identification file */
|
||||||
|
- def portFile(port: Int) = portsDir / File(port.toString)
|
||||||
|
+ def portFile(port: Int): File = portsDir / File(port.toString)
|
||||||
|
|
||||||
|
/** Poll for a server port number; return -1 if none exists yet */
|
||||||
|
private def pollPort(): Int = if (fixPort > 0) {
|
||||||
|
@@ -138,19 +126,19 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
}
|
||||||
|
info("[Port number: " + port + "]")
|
||||||
|
if (port < 0)
|
||||||
|
- fatal("Could not connect to compilation daemon after " + attempts + " attempts.")
|
||||||
|
+ fatal(s"Could not connect to compilation daemon after $attempts attempts. To run without it, use `-nocompdaemon` or `-nc`.")
|
||||||
|
port
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the port number to which a scala compile server is connected */
|
||||||
|
- def setPort(port: Int) {
|
||||||
|
- val file = portFile(port)
|
||||||
|
- val secret = new SecureRandom().nextInt.toString
|
||||||
|
-
|
||||||
|
- try file writeAll secret catch {
|
||||||
|
- case e @ (_: FileNotFoundException | _: SecurityException) =>
|
||||||
|
- fatal("Cannot create file: %s".format(file.path))
|
||||||
|
- }
|
||||||
|
+ def setPort(port: Int): Unit = {
|
||||||
|
+ val file = portFile(port)
|
||||||
|
+ // 128 bits of delicious randomness, suitable for printing with println over a socket,
|
||||||
|
+ // and storage in a file -- see getPassword
|
||||||
|
+ val secretDigits = new BigInteger(128, new SecureRandom()).toString.getBytes("UTF-8")
|
||||||
|
+
|
||||||
|
+ try OwnerOnlyChmod().chmodAndWrite(file.jfile, secretDigits)
|
||||||
|
+ catch chmodFailHandler(s"Cannot create file: ${file}")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Delete the port number to which a scala compile server was connected */
|
||||||
|
@@ -208,7 +196,7 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
|
||||||
|
def getPassword(port: Int): String = {
|
||||||
|
val ff = portFile(port)
|
||||||
|
- val f = ff.bufferedReader()
|
||||||
|
+ val f = ff.bufferedReader(Codec.UTF8)
|
||||||
|
|
||||||
|
// allow some time for the server to start up
|
||||||
|
def check = {
|
||||||
|
@@ -223,6 +211,24 @@ class CompileSocket extends CompileOutputCommon {
|
||||||
|
f.close()
|
||||||
|
result
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ private def chmodFailHandler(msg: String): PartialFunction[Throwable, Unit] = {
|
||||||
|
+ case NonFatal(e) =>
|
||||||
|
+ if (verbose) e.printStackTrace()
|
||||||
|
+ fatal(msg)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ def mkDaemonDir(name: String) = {
|
||||||
|
+ val dir = (scalacDir / name).createDirectory()
|
||||||
|
+
|
||||||
|
+ if (dir.isDirectory && dir.canWrite) info(s"[Temp directory: $dir]")
|
||||||
|
+ else fatal(s"Could not create compilation daemon directory $dir")
|
||||||
|
+
|
||||||
|
+ try OwnerOnlyChmod().chmod(dir.jfile)
|
||||||
|
+ catch chmodFailHandler(s"Failed to change permissions on $dir. The compilation daemon requires a secure directory; use -nc to disable the daemon.")
|
||||||
|
+ dir
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
|
||||||
|
index 9c2db11a56e..edfc095c7f7 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
|
||||||
|
@@ -38,8 +38,11 @@ class GenericRunnerSettings(error: String => Unit) extends Settings(error) {
|
||||||
|
|
||||||
|
val nc = BooleanSetting(
|
||||||
|
"-nc",
|
||||||
|
- "do not use the fsc compilation daemon") withAbbreviation "-nocompdaemon"
|
||||||
|
+ "do not use the fsc compilation daemon") withAbbreviation "-nocompdaemon" withPostSetHook((x: BooleanSetting) => {_useCompDaemon = !x.value })
|
||||||
|
|
||||||
|
@deprecated("Use `nc` instead", "2.9.0") def nocompdaemon = nc
|
||||||
|
@deprecated("Use `save` instead", "2.9.0") def savecompiled = save
|
||||||
|
+
|
||||||
|
+ private[this] var _useCompDaemon = true
|
||||||
|
+ def useCompDaemon: Boolean = _useCompDaemon
|
||||||
|
}
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/Properties.scala b/src/compiler/scala/tools/nsc/Properties.scala
|
||||||
|
index 55fd1967164..8b314ba0b82 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/Properties.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/Properties.scala
|
||||||
|
@@ -5,6 +5,8 @@
|
||||||
|
|
||||||
|
package scala.tools.nsc
|
||||||
|
|
||||||
|
+import scala.tools.nsc.io.Path
|
||||||
|
+
|
||||||
|
/** Loads `compiler.properties` from the jar archive file.
|
||||||
|
*/
|
||||||
|
object Properties extends scala.util.PropertiesTrait {
|
||||||
|
@@ -22,4 +24,7 @@ object Properties extends scala.util.PropertiesTrait {
|
||||||
|
// derived values
|
||||||
|
def isEmacsShell = propOrEmpty("env.emacs") != ""
|
||||||
|
def fileEndings = fileEndingString.split("""\|""").toList
|
||||||
|
+
|
||||||
|
+ // Where we keep fsc's state (ports/redirection)
|
||||||
|
+ lazy val scalacDir = (Path(Properties.userHome) / ".scalac").createDirectory(force = false)
|
||||||
|
}
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
|
||||||
|
index 107c4b3df3d..9af0079ffd6 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
|
||||||
|
@@ -77,7 +77,10 @@ class ScriptRunner extends HasCompileSocket {
|
||||||
|
val coreCompArgs = compSettings flatMap (_.unparse)
|
||||||
|
val compArgs = coreCompArgs ++ List("-Xscript", scriptMain(settings), scriptFile)
|
||||||
|
|
||||||
|
- CompileSocket getOrCreateSocket "" match {
|
||||||
|
+ // TODO: untangle this mess of top-level objects with their own little view of the mutable world of settings
|
||||||
|
+ compileSocket.verbose = settings.verbose.value
|
||||||
|
+
|
||||||
|
+ compileSocket getOrCreateSocket "" match {
|
||||||
|
case Some(sock) => compileOnServer(sock, compArgs)
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
@@ -109,14 +112,23 @@ class ScriptRunner extends HasCompileSocket {
|
||||||
|
|
||||||
|
settings.outdir.value = compiledPath.path
|
||||||
|
|
||||||
|
- if (settings.nc.value) {
|
||||||
|
- /** Setting settings.script.value informs the compiler this is not a
|
||||||
|
- * self contained compilation unit.
|
||||||
|
+ // can't reliably lock down permissions on the portfile in this environment => disable by default.
|
||||||
|
+ // not the cleanest to do this here, but I don't see where else to decide this and emit the warning below
|
||||||
|
+ val cantLockdown = !settings.nc.isSetByUser && scala.util.Properties.isWin && !scala.util.Properties.isJavaAtLeast("7")
|
||||||
|
+
|
||||||
|
+ if (cantLockdown) settings.nc.value = true
|
||||||
|
+
|
||||||
|
+ if (!settings.useCompDaemon) {
|
||||||
|
+ /* Setting settings.script.value informs the compiler this is not a
|
||||||
|
+ * self contained compilation unit.
|
||||||
|
*/
|
||||||
|
settings.script.value = mainClass
|
||||||
|
val reporter = new ConsoleReporter(settings)
|
||||||
|
val compiler = newGlobal(settings, reporter)
|
||||||
|
|
||||||
|
+ if (cantLockdown)
|
||||||
|
+ reporter.echo("[info] The compilation daemon is disabled by default on this platform. To force its usage, use `-nocompdaemon:false`.")
|
||||||
|
+
|
||||||
|
new compiler.Run compile List(scriptFile)
|
||||||
|
if (reporter.hasErrors) None else Some(compiledPath)
|
||||||
|
}
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala b/src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala
|
||||||
|
index dddfb1b8f64..5467c0a61ef 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala
|
||||||
|
@@ -7,14 +7,37 @@ package scala.tools.nsc
|
||||||
|
package interpreter
|
||||||
|
package session
|
||||||
|
|
||||||
|
-import scala.tools.nsc.io._
|
||||||
|
-import FileBackedHistory._
|
||||||
|
+import scala.reflect.internal.util.OwnerOnlyChmod
|
||||||
|
+import scala.reflect.io.{File, Path}
|
||||||
|
+import scala.tools.nsc.Properties.{propOrNone, userHome}
|
||||||
|
+import scala.util.control.NonFatal
|
||||||
|
|
||||||
|
/** TODO: file locking.
|
||||||
|
*/
|
||||||
|
trait FileBackedHistory extends JLineHistory with JPersistentHistory {
|
||||||
|
def maxSize: Int = 2500
|
||||||
|
- protected lazy val historyFile: File = defaultFile
|
||||||
|
+
|
||||||
|
+ // For a history file in the standard location, always try to restrict permission,
|
||||||
|
+ // creating an empty file if none exists.
|
||||||
|
+ // For a user-specified location, only lock down permissions if we're the ones
|
||||||
|
+ // creating it, otherwise responsibility for permissions is up to the caller.
|
||||||
|
+ protected lazy val historyFile: File = File {
|
||||||
|
+ propOrNone("scala.shell.histfile").map(Path.apply) match {
|
||||||
|
+ case Some(p) => if (!p.exists) secure(p) else p
|
||||||
|
+ case None => secure(Path(userHome) / FileBackedHistory.defaultFileName)
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private def secure(p: Path): Path = {
|
||||||
|
+ try OwnerOnlyChmod().chmodOrCreateEmpty(p.jfile)
|
||||||
|
+ catch { case NonFatal(e) =>
|
||||||
|
+ if (interpreter.isReplDebug) e.printStackTrace()
|
||||||
|
+ interpreter.replinfo(s"Warning: history file ${p}'s permissions could not be restricted to owner-only.")
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ p
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
private var isPersistent = true
|
||||||
|
|
||||||
|
locally {
|
||||||
|
@@ -79,6 +102,5 @@ object FileBackedHistory {
|
||||||
|
// val ContinuationNL: String = Array('\003', '\n').mkString
|
||||||
|
import Properties.userHome
|
||||||
|
|
||||||
|
- def defaultFileName = ".scala_history"
|
||||||
|
- def defaultFile: File = File(Path(userHome) / defaultFileName)
|
||||||
|
+ final val defaultFileName = ".scala_history"
|
||||||
|
}
|
||||||
|
diff --git a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala
|
||||||
|
index 1f6fa68f572..0673fa1f758 100644
|
||||||
|
--- a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala
|
||||||
|
+++ b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala
|
||||||
|
@@ -3,19 +3,18 @@
|
||||||
|
* @author Paul Phillips
|
||||||
|
*/
|
||||||
|
|
||||||
|
-package scala.tools.nsc
|
||||||
|
-package util
|
||||||
|
-
|
||||||
|
-import java.lang.{ ClassLoader => JClassLoader }
|
||||||
|
-import java.lang.reflect.{ Constructor, Modifier, Method }
|
||||||
|
-import java.io.{ File => JFile }
|
||||||
|
-import java.net.{ URLClassLoader => JURLClassLoader }
|
||||||
|
-import java.net.URL
|
||||||
|
-import scala.reflect.runtime.ReflectionUtils.unwrapHandler
|
||||||
|
-import ScalaClassLoader._
|
||||||
|
-import scala.util.control.Exception.{ catching }
|
||||||
|
+package scala.tools.nsc.util
|
||||||
|
+
|
||||||
|
+import java.io.{File => JFile}
|
||||||
|
+import java.lang.reflect.{Constructor, Modifier}
|
||||||
|
+import java.lang.{ClassLoader => JClassLoader}
|
||||||
|
+import java.net.{URL, URLClassLoader => JURLClassLoader}
|
||||||
|
+
|
||||||
|
import scala.language.implicitConversions
|
||||||
|
-import scala.reflect.{ ClassTag, classTag }
|
||||||
|
+import scala.reflect.runtime.ReflectionUtils.unwrapHandler
|
||||||
|
+import scala.reflect.{ClassTag, classTag}
|
||||||
|
+import scala.tools.nsc.io.Streamable
|
||||||
|
+import scala.util.control.Exception.catching
|
||||||
|
|
||||||
|
trait HasClassPath {
|
||||||
|
def classPathURLs: Seq[URL]
|
||||||
|
@@ -25,6 +24,8 @@ trait HasClassPath {
|
||||||
|
* of java reflection.
|
||||||
|
*/
|
||||||
|
trait ScalaClassLoader extends JClassLoader {
|
||||||
|
+ import ScalaClassLoader._
|
||||||
|
+
|
||||||
|
/** Executing an action with this classloader as context classloader */
|
||||||
|
def asContext[T](action: => T): T = {
|
||||||
|
val saved = contextLoader
|
||||||
|
@@ -52,7 +53,7 @@ trait ScalaClassLoader extends JClassLoader {
|
||||||
|
/** The actual bytes for a class file, or an empty array if it can't be found. */
|
||||||
|
def classBytes(className: String): Array[Byte] = classAsStream(className) match {
|
||||||
|
case null => Array()
|
||||||
|
- case stream => io.Streamable.bytes(stream)
|
||||||
|
+ case stream => Streamable.bytes(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An InputStream representing the given class name, or null if not found. */
|
||||||
|
diff --git a/src/reflect/scala/reflect/internal/util/OwnerOnlyChmod.scala b/src/reflect/scala/reflect/internal/util/OwnerOnlyChmod.scala
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000000..c0da65db387
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/reflect/scala/reflect/internal/util/OwnerOnlyChmod.scala
|
||||||
|
@@ -0,0 +1,107 @@
|
||||||
|
+/* NSC -- new Scala compiler
|
||||||
|
+ * Copyright 2017 LAMP/EPFL
|
||||||
|
+ * @author Martin Odersky
|
||||||
|
+ */
|
||||||
|
+package scala.reflect.internal.util
|
||||||
|
+
|
||||||
|
+import java.io.{File, FileOutputStream, IOException}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+trait OwnerOnlyChmod {
|
||||||
|
+ /** Remove group/other permissions for `file`, it if exists */
|
||||||
|
+ def chmod(file: java.io.File): Unit
|
||||||
|
+
|
||||||
|
+ /** Delete `file` if it exists, recreate it with no group/other permissions, and write `contents` */
|
||||||
|
+ final def chmodAndWrite(file: File, contents: Array[Byte]): Unit = {
|
||||||
|
+ file.delete()
|
||||||
|
+ val fos = new FileOutputStream(file)
|
||||||
|
+ fos.close()
|
||||||
|
+ chmod(file)
|
||||||
|
+ val fos2 = new FileOutputStream(file)
|
||||||
|
+ try {
|
||||||
|
+ fos2.write(contents)
|
||||||
|
+ } finally {
|
||||||
|
+ fos2.close()
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // TODO: use appropriate NIO call instead of two-step exists?/create!
|
||||||
|
+ final def chmodOrCreateEmpty(file: File): Unit =
|
||||||
|
+ if (!file.exists()) chmodAndWrite(file, Array[Byte]()) else chmod(file)
|
||||||
|
+
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+object OwnerOnlyChmod {
|
||||||
|
+ def apply(): OwnerOnlyChmod = {
|
||||||
|
+ if (!util.Properties.isWin) Java6UnixChmod
|
||||||
|
+ else if (util.Properties.isJavaAtLeast("7")) new NioAclChmodReflective
|
||||||
|
+ else NoOpOwnerOnlyChmod
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+object NoOpOwnerOnlyChmod extends OwnerOnlyChmod {
|
||||||
|
+ override def chmod(file: File): Unit = ()
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/** Adjust permissions with `File.{setReadable, setWritable}` */
|
||||||
|
+object Java6UnixChmod extends OwnerOnlyChmod {
|
||||||
|
+
|
||||||
|
+ def chmod(file: File): Unit = if (file.exists()) {
|
||||||
|
+ def clearAndSetOwnerOnly(f: (Boolean, Boolean) => Boolean): Unit = {
|
||||||
|
+ def fail() = throw new IOException("Unable to modify permissions of " + file)
|
||||||
|
+ // attribute = false, ownerOnly = false
|
||||||
|
+ if (!f(false, false)) fail()
|
||||||
|
+ // attribute = true, ownerOnly = true
|
||||||
|
+ if (!f(true, true)) fail()
|
||||||
|
+ }
|
||||||
|
+ if (file.isDirectory) {
|
||||||
|
+ clearAndSetOwnerOnly(file.setExecutable)
|
||||||
|
+ }
|
||||||
|
+ clearAndSetOwnerOnly(file.setReadable)
|
||||||
|
+ clearAndSetOwnerOnly(file.setWritable)
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+object NioAclChmodReflective {
|
||||||
|
+ val file_toPath = classOf[java.io.File].getMethod("toPath")
|
||||||
|
+ val files = Class.forName("java.nio.file.Files")
|
||||||
|
+ val path_class = Class.forName("java.nio.file.Path")
|
||||||
|
+ val getFileAttributeView = files.getMethod("getFileAttributeView", path_class, classOf[Class[_]], Class.forName("[Ljava.nio.file.LinkOption;"))
|
||||||
|
+ val linkOptionEmptyArray = java.lang.reflect.Array.newInstance(Class.forName("java.nio.file.LinkOption"), 0)
|
||||||
|
+ val aclFileAttributeView_class = Class.forName("java.nio.file.attribute.AclFileAttributeView")
|
||||||
|
+ val aclEntry_class = Class.forName("java.nio.file.attribute.AclEntry")
|
||||||
|
+ val aclEntryBuilder_class = Class.forName("java.nio.file.attribute.AclEntry$Builder")
|
||||||
|
+ val newBuilder = aclEntry_class.getMethod("newBuilder")
|
||||||
|
+ val aclEntryBuilder_build = aclEntryBuilder_class.getMethod("build")
|
||||||
|
+ val userPrinciple_class = Class.forName("java.nio.file.attribute.UserPrincipal")
|
||||||
|
+ val setPrincipal = aclEntryBuilder_class.getMethod("setPrincipal", userPrinciple_class)
|
||||||
|
+ val setPermissions = aclEntryBuilder_class.getMethod("setPermissions", Class.forName("[Ljava.nio.file.attribute.AclEntryPermission;"))
|
||||||
|
+ val aclEntryType_class = Class.forName("java.nio.file.attribute.AclEntryType")
|
||||||
|
+ val setType = aclEntryBuilder_class.getMethod("setType", aclEntryType_class)
|
||||||
|
+ val aclEntryPermission_class = Class.forName("java.nio.file.attribute.AclEntryPermission")
|
||||||
|
+ val aclEntryPermissionValues = aclEntryPermission_class.getDeclaredMethod("values")
|
||||||
|
+ val aclEntryType_ALLOW = aclEntryType_class.getDeclaredField("ALLOW")
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/** Reflective version of `NioAclChmod` */
|
||||||
|
+final class NioAclChmodReflective extends OwnerOnlyChmod {
|
||||||
|
+ import NioAclChmodReflective._
|
||||||
|
+ def chmod(file: java.io.File): Unit = {
|
||||||
|
+ val path = file_toPath.invoke(file)
|
||||||
|
+ val view = getFileAttributeView.invoke(null, path, aclFileAttributeView_class, linkOptionEmptyArray)
|
||||||
|
+ val setAcl = aclFileAttributeView_class.getMethod("setAcl", classOf[java.util.List[_]])
|
||||||
|
+ val getOwner = aclFileAttributeView_class.getMethod("getOwner")
|
||||||
|
+ val owner = getOwner.invoke(view)
|
||||||
|
+ setAcl.invoke(view, acls(owner))
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private def acls(owner: Object) = {
|
||||||
|
+ val builder = newBuilder.invoke(null)
|
||||||
|
+ setPrincipal.invoke(builder, owner)
|
||||||
|
+ setPermissions.invoke(builder, aclEntryPermissionValues.invoke(null))
|
||||||
|
+ setType.invoke(builder, aclEntryType_ALLOW.get(null))
|
||||||
|
+ java.util.Collections.singletonList(aclEntryBuilder_build.invoke(builder))
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
10
scala.spec
10
scala.spec
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
Name: scala
|
Name: scala
|
||||||
Version: 2.10.6
|
Version: 2.10.6
|
||||||
Release: 12
|
Release: 13
|
||||||
Summary: Combination of object-oriented and functional programming
|
Summary: Combination of object-oriented and functional programming
|
||||||
License: BSD and CC0 and Public Domain
|
License: BSD and CC0 and Public Domain
|
||||||
URL: http://www.scala-lang.org/
|
URL: http://www.scala-lang.org/
|
||||||
@ -24,6 +24,8 @@ Patch2: scala-2.10.3-compiler-pom.patch
|
|||||||
Patch3: scala-2.10.2-java7.patch
|
Patch3: scala-2.10.2-java7.patch
|
||||||
Patch4: scala-2.10-jline.patch
|
Patch4: scala-2.10-jline.patch
|
||||||
Patch5: scala-2.10.4-build_xml.patch
|
Patch5: scala-2.10.4-build_xml.patch
|
||||||
|
Patch6000: CVE-2017-15288-pre.patch
|
||||||
|
Patch6001: CVE-2017-15288.patch
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
|
|
||||||
BuildRequires: java-devel >= 1:1.7.0, ant, ant-junit, ant-contrib, jline >= 2.10, aqute-bnd, junit, javapackages-local, scala
|
BuildRequires: java-devel >= 1:1.7.0, ant, ant-junit, ant-contrib, jline >= 2.10, aqute-bnd, junit, javapackages-local, scala
|
||||||
@ -156,5 +158,11 @@ update-mime-database %{?fedora:-n} %{_datadir}/mime > /dev/null 2>&1 || :
|
|||||||
/usr/share/maven*
|
/usr/share/maven*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Dec 26 2019 zhujunhao <zhujunhao5@huawei.com> - 2.10.6-13
|
||||||
|
- Type:cves
|
||||||
|
- ID:CVE-2017-15288
|
||||||
|
- SUG:restart
|
||||||
|
- DESC:fix CVE-2017-15288
|
||||||
|
|
||||||
* Fri Dec 13 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.10.6-12
|
* Fri Dec 13 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.10.6-12
|
||||||
- Package init
|
- Package init
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user